importPackage(Packages.de.elo.ix.client);

//@include lib_Class.js

/**
 * Contact management utilities
 *
 * @author JHR, ELO Digital Office GmbH
 * @version 1.05.002
 *
 * @eloix
 * @eloas
 *
 * @requires handlebars
 * @requires sol.common.Config
 * @requires sol.common.IxUtils
 * @requires sol.common.StringUtils
 * @requires sol.common.AclUtils
 * @requires sol.common.RepoUtils
 * @requires sol.common.SordUtils
 * @requires sol.common.WfUtils
 * @requires sol.common.Template
 */
sol.define("sol.contact.Utils", {
  singleton: true,

  /**
   * Loads (and merges) the contact configuration from the JSON file: `/Administration/Business Solutions/contact/Configuration/contact.config`
   * @return {Object}
   */
  loadConfig: function () {
    return sol.create("sol.common.Config", { compose: "/contact/Configuration/contact.config" }).config;
  },

  /**
   * Get config part
   * @param {Object} config Configuration
   * @param {de.elo.ix.client.Sord} sord
   * @return {Object} Configuration part
   */
  getConfigPart: function (config, sord) {
    var configPart;

    if (!config) {
      throw "Configuation is empty";
    }

    if (!sord) {
      throw "Sord is empty";
    }

    if (sol.contact.Utils.isContactList(sord)) {
      configPart = sol.common.ObjectUtils.clone(config.contactlist);
    } else if (sol.contact.Utils.isCompany(sord)) {
      configPart = sol.common.ObjectUtils.clone(config.company);
    } else if (sol.contact.Utils.isContact(sord)) {
      configPart = sol.common.ObjectUtils.clone(config.contact);
    } else {
      throw "Type must be contact list, company or contact";
    }

    return configPart;
  },

  /**
   * Checks, if an element is from type contactlist
   * @param {String|de.elo.ix.client.Sord} sord This can either be a objId or a Sord object
   * @return {Boolean}
   */
  isContactList: function (sord) {
    var me = this;
    return me.getSolType(sord) === me.loadConfig().contactlist.solType;
  },

  /**
   * Searches the repository hierarchy to find the parent contactlist (if there is any).
   * @param {String} objId
   * @return {de.elo.ix.client.Sord}
   */
  getParentContactList: function (objId) {
    var me = this,
        sord = ixConnect.ix().checkoutSord(objId, SordC.mbAllIndex, LockC.NO),
        isContactList = me.isContactList(sord);

    if (!isContactList && sord.id !== 1 && sord.parentId !== 0) {
      return me.getParentContactList(sord.parentId);
    }
    return (isContactList) ? sord : null;
  },

  /**
   * Checks, if an element is from type company
   * @param {String|de.elo.ix.client.Sord} sord This can either be a objId or a Sord object
   * @return {Boolean}
   */
  isCompany: function (sord) {
    var me = this;
    return me.getSolType(sord) === me.loadConfig().company.solType;
  },

  /**
   * Searches the repository hierarchy to find the parent company (if there is any).
   * @param {String} objId
   * @return {de.elo.ix.client.Sord}
   */
  getParentCompany: function (objId) {
    var me = this,
        sord,
        isCompany, isContactList;

    sord = ixConnect.ix().checkoutSord(objId, SordC.mbAllIndex, LockC.NO);
    isCompany = me.isCompany(sord);
    isContactList = me.isContactList(sord);

    if (!isCompany && !isContactList && sord.id !== 1 && sord.parentId !== 0) {
      return me.getParentCompany(sord.parentId);
    }
    return (isCompany) ? sord : null;
  },

  /**
   * Checks, if an element is from type contact
   * @param {String|de.elo.ix.client.Sord} sord This can either be a objId or a Sord object
   * @return {Boolean}
   */
  isContact: function (sord) {
    var me = this;
    return me.getSolType(sord) === me.loadConfig().contact.solType;
  },

  /**
   * Searches the repository hierarchy to find the parent contact (if there is any).
   * @param {String} objId
   * @return {de.elo.ix.client.Sord}
   */
  getParentContact: function (objId) {
    var me = this,
        sord = ixConnect.ix().checkoutSord(objId, SordC.mbAllIndex, LockC.NO),
        isContact = me.isContact(sord);

    if (!isContact && sord.id !== 1 && sord.parentId !== 0) {
      return me.getParentContact(sord.parentId);
    }
    return (isContact) ? sord : null;
  },

  /**
   * Checks, if an element is from type of contact management object
   * @param {String|de.elo.ix.client.Sord} sord This can either be a objId or a Sord object
   * @return {Boolean}
   */
  isContactManagementObject: function (sord) {
    var me = this;
    return me.isContactList(sord) || me.isCompany(sord) || me.isContact(sord);
  },

  /**
   * Searches the registerfolder for a prefix.
   * @param {String} objId
   * @param {String} regPrefix, e.g. 'A'
   * @return {String} objId of registerfolder
   */
  getIdRegisterFolder: function (objId, regPrefix) {
    var repoPath = sol.common.RepoUtils.getPathFromObjId(objId),
        regId;

    repoPath = repoPath + "/" + regPrefix;
    regId = sol.common.RepoUtils.preparePath(repoPath);
    return (regId);
  },

  /**
   * @private
   * @param {de.elo.ix.client.Sord} sord
   * @return {String}
   */
  getSolType: function (sord) {
    var solType = sol.common.SordUtils.getObjKeyValue(sord, "SOL_TYPE");
    return (solType) ? solType + "" : null;
  },

  /**
   * Creates a new company in the chaos cabinet.
   * @param {String} companyType Used to determine the company template.
   * @param {Object} params (optional)
   * @param {de.elo.ix.client.UserInfo} params.owner (optional) This user will be granted full access to the new company element
   * @param {Boolean} [params.fromService=false] (optional) This will be reflected in the new elements name (used for further processing)
   * @return {Object} Result contains `objId` of the new element and `name` of the new element
   */
  createCompany: function (companyType, params) {
    var me = this,
        result = {},
        aclCfg = null;

    me.logger.enter("create_company", arguments);

    result.name = me.buildCompanyTempName(companyType, (params && params.fromService) ? params.fromService : false);

    if (params && params.owner) {
      aclCfg = {
        mode: "ADD",
        entries: [
          { userName: params.owner.name, rights: { r: true, w: true, d: true, e: true, l: true } }
        ]
      };
    }

    result.objId = sol.common.IxUtils.execute("RF_sol_function_CopyFolderContents", {
      objId: "0",
      source: me.getCompanyTemplateObjId(companyType),
      copySourceAcl: false,
      inheritDestinationAcl: false,
      name: result.name,
      asAdmin: true,
      useQuickCopy: true,
      acl: aclCfg
    });

    me.logger.exit("create_company", result);

    return result;
  },

  /**
   * @private
   * Retrieves the path of the company template.
   * @param {String} companyType
   * @return {String}
   */
  getCompanyTemplateObjId: function (companyType) {
    var me = this;
    return sol.common.RepoUtils.getObjIdFromRelativePath(me.loadConfig().company.templateFolderId, "/" + companyType);
  },

  /**
   * Retrieves the company reference.
   * @param {String|de.elo.ix.client.Sord} sord This can either be a objId or a Sord object
   * @return {String} The company reference or `null` if no reference was found
   */
  getCompanyReference: function (sord) {
    var me = this,
        companyRef = null;

    me.logger.enter("getCompanyReference", { objId: sord.id || sord });

    if (!sol.common.SordUtils.isSord(sord)) {
      sord = ixConnect.ix().checkoutSord(sord, SordC.mbAllIndex, LockC.NO);
    }

    companyRef = sol.common.SordUtils.getObjKeyValue(sord, me.loadConfig().company.referenceField);
    companyRef = (companyRef && !sol.common.StringUtils.isBlank(companyRef)) ? String(companyRef) : null;

    me.logger.exit("getCompanyReference", { companyReference: companyRef });

    return companyRef;
  },

  /**
   * @private
   * Creates the new company (temporary) name.
   * @param {String} companyType
   * @param {Boolean} [fromService=false] (optional) If `true`, a prefix will be set that the element / workflow can be recoqnised (uses {@link sol.common.WfUtils#createServiceWfName})
   * @return {String}
   */
  buildCompanyTempName: function (companyType, fromService) {
    var me = this,
        name;
    name = sol.create("sol.common.Template", { source: me.loadConfig().company.createWorkflowNameTemplate }).apply({ companyType: companyType });
    if (fromService === true) {
      name = sol.common.WfUtils.createServiceWfName(name);
    }
    return name;
  },

  /**
   * Creates a new contact in the chaos cabinet.
   * @param {String} contactType Used to determine the contact template.
   * @param {Object} params (optional)
   * @param {de.elo.ix.client.UserInfo} params.owner (optional) This user will be granted full access to the new contact element
   * @param {Boolean} [params.fromService=false] (optional) This will be reflected in the new elements name (used for further processing)
   * @return {Object} Result contains `objId` of the new element and `name` of the new element
   */
  createContact: function (contactType, params) {
    var me = this,
        result = {},
        aclCfg = null;

    me.logger.enter("create_contact", arguments);

    result.name = me.buildContactTempName(contactType, (params && params.fromService) ? params.fromService : false);

    if (params && params.owner) {
      aclCfg = {
        mode: "ADD",
        entries: [
          { userName: params.owner.name, rights: { r: true, w: true, d: true, e: true, l: true } }
        ]
      };
    }

    result.objId = sol.common.IxUtils.execute("RF_sol_function_CopyFolderContents", {
      objId: "0",
      source: me.getContactTemplateObjId(contactType),
      copySourceAcl: false,
      inheritDestinationAcl: false,
      name: result.name,
      asAdmin: true,
      useQuickCopy: true,
      acl: aclCfg
    });

    me.logger.exit("create_contact", result);

    return result;
  },

  /**
   * @private
   * Retrieves the path of the contact template.
   * @param {String} contactType
   * @return {String}
   */
  getContactTemplateObjId: function (contactType) {
    var me = this;
    return sol.common.RepoUtils.getObjIdFromRelativePath(me.loadConfig().contact.templateFolderId, "/" + contactType);
  },

  /**
   * Retrieves the contact reference.
   * @param {String|de.elo.ix.client.Sord} sord This can either be a objId or a Sord object
   * @return {String} The contact reference or `null` if no reference was found
   */
  getContactReference: function (sord) {
    var me = this,
        contactRef = null;

    me.logger.enter("getContactReference", { objId: sord.id || sord });

    if (!sol.common.SordUtils.isSord(sord)) {
      sord = ixConnect.ix().checkoutSord(sord, SordC.mbAllIndex, LockC.NO);
    }

    contactRef = sol.common.SordUtils.getObjKeyValue(sord, me.loadConfig().contact.referenceField);
    contactRef = (contactRef && !sol.common.StringUtils.isBlank(contactRef)) ? String(contactRef) : null;

    me.logger.exit("getContactReference", { contactReference: contactRef });

    return contactRef;
  },

  /**
   * @private
   * Creates the new contact (temporary) name.
   * @param {String} contactType
   * @param {Boolean} [fromService=false] (optional) If `true`, a prefix will be set that the element / workflow can be recoqnised (uses {@link sol.common.WfUtils#createServiceWfName})
   * @return {String}
   */
  buildContactTempName: function (contactType, fromService) {
    var me = this,
        name;
    name = sol.create("sol.common.Template", { source: me.loadConfig().contact.createWorkflowNameTemplate }).apply({ contactType: contactType });
    if (fromService === true) {
      name = sol.common.WfUtils.createServiceWfName(name);
    }
    return name;
  },

  /**
   * Maps the data from the batch importer so it can be used by the existing createX RFs.
   * @param {Object} templateSord
   * @return {Object[]} An input object array for the {@link sol.common.SordUtils#updateSord updateSord} method.
   */
  mapData: function (templateSord) {
    var result = [],
        mapSubObj;

    mapSubObj = function (obj, type) {
      var key;
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          result.push({ key: key, type: type, value: obj[key] });
        }
      }
    };

    if (!templateSord) {
      return result;
    }

    if (templateSord.objKeys) {
      mapSubObj(templateSord.objKeys, "GRP");
    }

    if (templateSord.mapKeys) {
      mapSubObj(templateSord.mapKeys, "MAP");
    }

    return result;
  }

});