define(['underscore', 'utils', 'ms.api'], function (_, Utils, MsApi) {
    var Config = {};

    var defaultConfiguration = {
      networkDomain: 'com',
      customAdapterHost: null,
      idpLoginUrl: null,
      enableLoginWithoutSSO: null,
      click2DialSearch: null,
      noMatchObject: 'none',
      predefinedCampaignFieldName: null,
      customEntities: '',
      adapterDisplayMode: 'Embedded',
      multichannelSupport: false,
      supportedEntities: JSON.stringify([]),
      wildcardAniSearch: true,
      entityConfiguration: JSON.stringify({}),
      newInteractionPopup: false,
      supportedEntitiesPriority: JSON.stringify({})
    };

    var _readyPromise = null;

    Config.init = function () {
        if (_readyPromise) {
            return _readyPromise;
        }
        Config._five9ConfigurationMeta = require('metadata').getByLogicalName('five9_configuration');
        Config.Property =
          _.mapObject(Config._five9ConfigurationMeta.fieldMap, function(val, key) {
            return key;
          });

        _readyPromise = MsApi.retrieveMultipleRecords({
          entityMetadata: Config._five9ConfigurationMeta,
          top: 1
        }).then(
            function (res) {
                if (res[0]) {
                    Config._configuration = _.mapObject(res[0], function(val, key) {
                      return _.isNull(val) ? defaultConfiguration[key] : val;
                    });
                    if (Config._configuration.customEntities !== '') {
                      Config._migrateEntities();
                    }
                } else {
                    Config._configuration = defaultConfiguration;
                }
                return Promise.resolve();
            });

        return _readyPromise;
    };

    Config._migrateEntities = function() {
      var supportedEntities = JSON.parse(Config._configuration.customEntities);
      Array.prototype.push.apply(supportedEntities, require('metadata').defaultSearchEntities);

      Config._configuration.supportedEntities = JSON.stringify(supportedEntities);
      Config._configuration.customEntities = '';
    };

    Config.flush = function (doneCb, failCb) {
        Config._checkInit();

        var guid = Config.get(Config.Property.id);
        if (guid) {
            MsApi.updateRecord({
              entityMetadata: Config._five9ConfigurationMeta,
              id: guid,
              entityData: Config._configuration
            }).then(doneCb, failCb);
        } else {
            MsApi.createRecord({
              entityMetadata: Config._five9ConfigurationMeta,
              entityData: Config._configuration
            }).then(
                function (record) {
                    _.extend(Config._configuration, record);
                    doneCb();
                },
                failCb);
        }
    };

    Config.reset = function (doneCb, failCb) {
        Config._checkInit();

        _.extend(Config._configuration, defaultConfiguration);

        Config.flush(doneCb, failCb);
    };

    Config.get = function (prop) {
        Config._checkInit();

        if (prop === Config.Property.customEntities ||
            prop === Config.Property.supportedEntities ||
            prop === Config.Property.entityConfiguration ||
            prop === Config.Property.supportedEntitiesPriority) {
          return JSON.parse(Config._configuration[prop]);
        } else {
          return Config._configuration[prop];
        }
    };

    Config.set = function (prop, value) {
        Config._checkInit();

        if (prop === Config.Property.customEntities ||
            prop === Config.Property.supportedEntities ||
            prop === Config.Property.entityConfiguration ||
            prop === Config.Property.supportedEntitiesPriority) {
          Config._configuration[prop] = JSON.stringify(value);
        } else {
          Config._configuration[prop] = value;
        }
    };

    Config._checkInit = function () {
        if (!Config._configuration) {
            throw 'Config is not initialized';
        }
    };

    Config.getDefaultEntityConfig = function(logicalName) {
      return {
        phone_fields: '',
        email_fields: '',
        use_active_query: false,
        active_query: '',
        voice: {
          search_type: 'fields',
          search_query: ''
        },
        text: {
          search_type: 'fields',
          search_query: ''
        },
        type: Config.getDefaultEntityType(logicalName)
      };
    };

    Config.getDefaultEntityType = function(logicalName) {
      return (logicalName === 'contact' || logicalName === 'account' || logicalName === 'lead') ? 'name' : 'related';
    };

    return Config;
});
