(function (exports) {
  'use strict';

  var Oauth3Config;
  var Oauth3 = (exports.OAUTH3 || require('./oauth3'));

  function create(instanceOpts) {
    var me = {};
    var storage = instanceOpts.storage;

    me.defaults = instanceOpts.defaults;
    me.libPrefix = instanceOpts.libPrefix;

    me.init = function (opts) {
      console.log('DEBUG Oauth3Config.create.init');
      console.log(opts);

      // TODO get multiple keys at once
      return Oauth3.PromiseA.all([
        storage.get('dev.providerUri').then(function (val) {
          console.log('DEBUG oauth3.init providerUri', val);
          me.developerMode = true;
          me.providerUri = val;
          me.providerUriSet = true;

        }, function () {
          // ignore
        })
      , storage.get('dev.apiBaseUri').then(function (val2) {
          console.log('DEBUG oauth3.init apiBaseUri', val2);
          me.apiBaseUri = val2;
          me.apiBaseUriSet = true;

        }, function () {
          // ignore
        })
      ]).then(function () {
        console.log('DEBUG oauth3.init complete');

        Object.keys(opts).forEach(function (key) {
          if ('appSecret' === key) {
            window.alert("[ERROR] appSecret must never be used in a client (browser, mobile, or desktop)");
            return;
          }
          me[key] = opts[key];
        });

        Object.keys(me.defaults).forEach(function (key) {
          if ('undefined' === typeof me[key]) {
            me[key] = me.defaults[key];
          }
        });

        if (!me.appId) {
          if (me.clientUri || me.clientAgreeTos) {
            if (!(me.clientUri && me.clientAgreeTos)) {
              console.error("Please set `DaplieApiConfig.clientUri` and `DaplieApiConfig.clientAgreeTos`, try these:");
              console.log("    oauth3.org");
              console.log("    oauth3.org/tos/draft");
              window.alert("[ERROR] `DaplieApiConfig.clientUri` and `DaplieApiConfig.clientAgreeTos` not set."
                + "\nTest with 'oauth3.org' 'oauth3.org/tos/draft'");
            }
          }
          else {
            console.error("Please set `DaplieApiConfig.appId`, try this:");
            console.log("    TEST_ID_xxxxxxxxxxxxxxxxxxxxxxxx");
            console.log("    (NOT YET IMPLEMENTED)");
            window.alert("[ERROR] `DaplieApiConfig.appId` not set.\nTest with 'TEST_ID_xxxxxxxxxxxxxxxxxxxxxxxx'");
          }
        }

        console.log('');
        if (!me.providerUriSet) {
          console.info("Why, hello there Fellow Developer! Would you like to test against the beta server?");
          console.log("    " + me.libPrefix + "Daplie.storage.set('dev.providerUri', 'https://betapool.com')");
          console.log("    " + me.libPrefix + "Daplie.storage.set('dev.apiBaseUri', 'https://betapool.io')");
          console.log('');
        }
        if (me.providerUriSet || me.apiBaseUriSet) {
          console.info("You're in Developer Mode! :-)");
          console.log("    UI:  " + me.providerUri);
          console.log("    API: " + me.apiBaseUri);
          console.log('');

          console.log("Want to switch back to production mode?");
          console.log("    " + me.libPrefix + "Daplie.storage.remove('dev.providerUri'); "
            + me.libPrefix + "Daplie.storage.remove('dev.apiBaseUri');");
          console.log('');
        }
      }).then(function () {
        // Note: it is possible for this to fail (i.e. when offline or providerUri is bad).
        // Note: for development you can pass in opts.directives (in the format of oauth3.json)
        console.log('DEBUG oauth3 discover start');
        return Oauth3.discover(me.providerUri, opts).then(function () {
          console.log('DEBUG oauth3 discover end');
          console.log(me);
          return me;
        });
      });
    };

    return me;
  }

  Oauth3Config = {
    create: create
  };
  exports.Oauth3Config = Oauth3Config.Oauth3Config = Oauth3Config;

  if ('undefined' !== typeof module) {
    module.exports = Oauth3Config;
  }
}('undefined' !== typeof exports ? exports : window));
