//@include lib_Class.js
//@include lib_sol.common.ObjectFormatter.js
//@include lib_sol.common.ix.FunctionBase.js

/**
 * Base class to generate IDs and names by templates
 *
 * A sub class must implement the methods `getIdentifierTemplateId`, `getIdentifier` and `setIdentifier`
 *
 * @author MW, ELO Digital Office GmbH
 * @version 1.01.002
 *
 * @eloix
 *
 * @requires  sol.common.JsonUtils
 * @requires  sol.common.ix.RfUtils
 * @requires  sol.common.WfUtils
 * @requires  sol.common.ix.FunctionBase
 */

sol.define("sol.common.ix.functions.GenerateIdentifier", {
  extend: "sol.common.ix.FunctionBase",

  /**
   * @cfg {String} identifierCounterTemplateId (required)
   * Object ID of the identifier counter template
   */

  /**
   * @cfg {String} identifierTemplateId (required)
   * Object ID of the identifier template
   */

  /**
   * @cfg {String} objId (required)
   * Object ID of destination object
   */

  /**
   * @cfg {String} fieldName (required)
   * Field name of the identifier field
   */

  /**
   * @cfg {Boolean} [applyIdentifier=false]
   * `True` if the identifier should be written to the object
   */

  /**
   * @cfg {Boolean} [optionalIdentifier=false]
   * If `true`, nothing will be generated if the generator field is empty
   */

  /**
   * @cfg {Boolean} [updateExisting=false]
   * If `true`, an existing value will be overridden
   */

  process: function () {
    var me = this,
        identifierTemplate, identifier;

    me.readObject();

    me.identifierTemplateId = me.identifierTemplateId || me.getIdentifierTemplateId();

    if (me.identifierTemplateId && me.updateIdentifier()) {

      identifierTemplate = sol.create("sol.common.Template", {});
      identifierTemplate.load(me.identifierTemplateId);
      identifier = identifierTemplate.apply({
        sord: me.templateSord
      });

      if (me.applyIdentifier && me.checkUpdate(identifier)) {
        me.setIdentifier(identifier);
        ixConnect.ix().checkinSord(me.sord, SordC.mbAllIndex, LockC.NO);
      }

      return JSON.stringify({ identifier: identifier });
    }
    return "";
  },

  /**
   * @private
   */
  readObject: function () {
    var me = this,
        templateSordFormatter;
    if (!me.objId) {
      throw "Object ID is empty";
    }
    me.sord = ixConnect.ix().checkoutSord(me.objId, SordC.mbAllIndex, LockC.NO);
    templateSordFormatter = sol.create("sol.common.ObjectFormatter.TemplateSord", {
      data: me.sord,
      config: {
        sordKeys: ["name", "IDateIso", "XDateIso"],
        objKeys: [],
        mapKeys: []
      }
    });
    me.templateSord = templateSordFormatter.build();
  },

  /**
   * @private
   * @return {Boolean} status
   */
  updateIdentifier: function () {
    var me = this;
    return me.updateExisting || org.apache.commons.lang.StringUtils.isBlank(me.getIdentifier());
  },

  /**
   * @private
   * @param {String} identifier
   * @return {Boolean}
   */
  checkUpdate: function (identifier) {
    var me = this;
    return (identifier != me.getIdentifier());
  },

  /**
   * @abstract
   * Must return the Object ID of the template.
   */
  getIdentifierTemplateId: function () {
    throw "Can't call abstract method 'getIdentifierTemplateId()'";
  },

  /**
   * @abstract
   * Must read the identifier from the appropriate field
   */
  getIdentifier: function () {
    throw "Can't call abstract method 'getIdentifier()'";
  },

  /**
   * Must write the identifier to the appropriate field
   * @abstract
   * @param {String} identifier Identifier
   */
  setIdentifier: function (identifier) {
    throw "Can't call abstract method 'setIdentifier()'";
  },

  /**
   * Reads the template name from generator field and determinates the object ID of the template
   * @private
   * @param {String} typeDescription
   * @param {String} templateNameField
   * @param {String} templateFolderId
   * @return {String} templateid
   */
  getTemplateId: function (typeDescription, templateNameField, templateFolderId) {
    var me = this,
        templateName;

    me.logger.debug("getTemplateId(): typeDescription=" + typeDescription + ", templateNameField=" + templateNameField + ", templateFolderId=" + templateFolderId);

    if (!templateNameField) {
      throw typeDescription + " template name field must not be empty.";
    }
    templateName = sol.common.SordUtils.getObjKeyValue(me.sord, templateNameField);

    me.logger.debug("getTemplateId(): templateName=" + templateName + ", optionalIdentifier=" + me.optionalIdentifier);
    return me.getObjIdFromRelativePath(typeDescription, templateName, templateFolderId);
  },

  /**
   * Get the ObjId of the selected templateFolder.
   *
   * @param {String} typeDescription
   * @param {String} templateFolderId
   * @param {String} templateName
   * @return {String} templateObjId
   */
  getObjIdFromRelativePath: function (typeDescription, templateName, templateFolderId) {
    var me = this;

    if (!templateName && me.optionalIdentifier) {
      return null;
    } else if (!templateName) {
      throw typeDescription + " template name must not be empty.";
    }
    if (!templateFolderId) {
      throw typeDescription + " template folder ID must not be empty.";
    }
    return sol.common.RepoUtils.getObjIdFromRelativePath(templateFolderId, "/" + templateName);
  },

  /**
   * @protected
   * Truncates a string to the appropriate length for the sord name field.
   * @param {String} name
   * @return {String}
   */
  truncateSordName: function (name) {
    var me = this,
        maxLength = ixConnect.CONST.SORD.lnName;

    name = (name) ? String(name) : name;

    if (name && (name.length > maxLength)) {
      name = name.substring(0, maxLength - 3) + "...";
      me.logger.debug("String truncated: " + name);
    }

    return name;
  }

});