api.require({
  namespace: ["sol"]
}, function () {

	/**
	 * This is a utility class for user interaction.
	 */
  sol.define("sol.common.web.ApiUtils", {
    singleton: true,
    /**
     * Finds a users workflow node based on its flowId and nodeId.
     * Since collecting tasks is expensive, the guid should be passed in order to limit search results.
     * A maximum of 100 tasks is retrieved in order to find the required node.
 *
     * @param {String} guid
     * @param {String} flowId
     * @param {String} nodeId
     * @param {Object} successFct
     * @param {Object} failureFct
     */
    getWfNode: function (guid, flowId, nodeId, successFct, failureFct) {
      var findTaskInfo = new de.elo.ix.client.FindTasksInfo();
      findTaskInfo.allUsers = false;
      findTaskInfo.inclWorkflows = true;
      findTaskInfo.objId = guid;
      findTaskInfo.highestPriority = elo.CONST.USER_TASK_PRIORITY.HIGHEST;
      findTaskInfo.lowestPriority = elo.CONST.USER_TASK_PRIORITY.LOWEST;
      findTaskInfo.sortOrder = elo.CONST.USER_TASK_SORT_ORDER.PRIORITY_DATE_NAME_INV;

      elo.IX.ix().findFirstTasks(findTaskInfo, 100, new de.elo.ix.client.AsyncCallback(function (findResult) {
        // success
        var tasks = findResult.tasks,
            task, i;
        for (i = 0; i < tasks.length; i++) {
          task = tasks[i];
          if (task.wfNode.flowId === flowId && task.wfNode.nodeId === nodeId) {
            successFct.call(this, task.wfNode);
            return;
          }
        }
        if (failureFct) {
          failureFct.call(this, "Workflow node not found.");
        }
      }, function (ex) {
        if (failureFct) {
          failureFct.call(this, ex);
        }
      }));
    },

    /**
     * Displays an info box.
     * @param {String} msg
     */
    showInfoMessage: function (msg) {
      elo.ModelRegistry.setDataInstance({
        scope: this,
        id: elo.ModelRegistry.getModelConstant("logMessage"),
        obj: {
          displayType: "window",
          type: "info",
          title: "",
          bodyTitle: msg
        }
      });
    },

    /**
     * Displays a toast/ message popup.
     * @param {String} msg
     */
    showPopupMessage: function (msg) {
      var me = this;

      elo.ModelRegistry.setDataInstance({
        scope: me,
        id: elo.ModelRegistry.getModelConstant("logMessage"),
        obj: {
          displayType: "popup",
          bodyTitle: msg
        }
      });
    }
  });
});

//# sourceURL=sol.common.web.ApiExtensions.js


api.require({
  namespace: ["sol"]
}, function () {

  var chars = [],
      pressed = false,
      timeout,
      minBarcodeLength;

  /**
   * @private
   *
   * This is an experimental class that might change in the future.
   * Don't rely on its existance.
   */
  sol.define("sol.common.web.BarcodeHandler", {
    singleton: true,

    initialize: function (config) {
      var me = this;
      me.$super("sol.Base", "initialize", arguments);

      window.addEventListener("keypress", me.handleKeyEvent);
      timeout = me.timeout;
      minBarcodeLength = me.minBarcodeLength;
    },

    /**
     * @cfg {Number} minimum amount of characters that identifies a barcode.
     */
    minBarcodeLength: 10,
    /**
     * @cfg {Number} timout in ms for the barcode sequence.
     */
    timeout: 500,

    handleKeyEvent: function (e) {
      chars.push(String.fromCharCode(e.which));
      if (pressed == false) {
        setTimeout(function () {
          if(chars.length >= minBarcodeLength) {
            var barcode = chars.join("");
            sol.common.web.BarcodeHandler.handleBarcode(barcode);
          }
          chars = [];
          pressed = false;
        }, timeout);
      }
      pressed = true;
    },
    handleBarcode: function (barcode) {
      var me = this,
          regex, guid, objId;
      me.logger.info("Barcode scanned: " + barcode);
      // if barcode was regognized in child component,
      // redirect to parent handler.
      if (api &&
          api.communication &&
          api.communication.Parent &&
          api.communication.Parent.hasParent()) {
        me.logger.info("Barcode scanned within child component. Redirect to parent.");

        // not implemented yet.

        return;
      }

      if (barcode.indexOf("elodms") == 0) {
          // handle wrong char set by some barcode readers [- equals ?ß]
        if (barcode.indexOf("elodmsÖ--") == 0) {
          barcode = barcode.replace(/[?ß]/g, "-");
        }
        regex = /[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}/i.exec(barcode);
        if (regex) {
          guid = "("+ regex[0] + ")";
          me.logger.info("Barcode contains elodms link. Goto element with GUID: " + guid);
          try {
            objId = elo.IX.ix().checkoutSord(guid, elo.CONST.SORD.mbOnlyId, elo.CONST.LOCK.NO).id;
            api.Webclient.gotoEntry(objId);
          } catch(e) {
            me.logger.info("Object not found for GUID: " + guid);
          }
        } else {
          me.logger.info("Barcode contains wrong guid format: " + guid);
        }
      } else if (sol.common.web.BarcodeRegistry.isValidBarcode(barcode)) {
        sol.common.web.BarcodeRegistry.execute(barcode);
      }
    }

  });

});


api.require({
  namespace: ["sol"]
}, function () {

  /**
   * @private
   *
   * This is an experimental class that might change in the future.
   * Don't rely on its existance.
   */
  sol.define("sol.common.web.BarcodeRegistry", {
    singleton: true,
    splitCharacter: ".",

    /**
     * @property registered barcode handlers
     * @private
     */
    registeredHandlers: {},

    /**
     * registers a new handler for incoming barcodes.
     * @param {String} identifier
     * @param {String} name name for the barcode handler
     * @param {function} handler
     */
    register: function (identifier, name, handler) {
      var me = this;
      me.logger.info(["Register handler '{1}' for identifier '{0}'.", identifier, name]);
      if (me.registeredHandlers.hasOwnProperty(identifier)) {
        me.logger.warn(["Override exisiting barcode handler for {0}.", identifier]);
      }
      me.registeredHandlers[identifier] = {
        name: name,
        handler: handler
      };
    },

    /**
     * processes and executes a barcode by its handler.
     * @param {String} barcode
     * @return {Boolean}
     */
    execute: function (barcode) {
      var me = this,
          parts,
          objId,
          identifier;

      if (!me.isValidBarcode(barcode)) {
        return false;
      }

      parts = barcode.split(me.splitCharacter);
      identifier = parts[0];
      objId = Number.parseFloat(parts[1]) || undefined;

      if (me.registeredHandlers.hasOwnProperty(identifier)
              && me.registeredHandlers[identifier].handler) {
        me.registeredHandlers[identifier].handler.call(me, identifier, objId, {
          parts: parts,
          barcode: barcode
        });
      } else {
        sol.common.web.ApiUtils.showPopupMessage("No handler found for barcode");
      }
      return true;
    },

    /**
     * checks if a given barcode is a valid source for executing actions.
     * @param {String} barcode
     * @return {Boolean}
     */
    isValidBarcode: function (barcode) {
      var me = this;
      return (barcode.indexOf(me.splitCharacter) > 0);
    }
  });
});

api.require({
  namespace: ["sol"],
  locales: ["sol.common.client.ActionHandler"]
}, function (locales) {

  /**
   * This class provides helper functions for executing complex actions.
   *
   * @elojc
   * @requires sol.common.web.ActionHandler
   */
  sol.define("sol.common.web.ActionHelper", {
    singleton: true,

    executeSimpleAction: function (objId, cfg) {
      var me = this,
          cfgObject;

      elo.helpers.Console.info("[sol.common.web.ActionHelper] executing advanced action on objId: " + objId, cfg);

      if (!cfg || !cfg.fct) {
        throw "executing a simple action requires mandatory config properties.";
      }

      cfgObject = (cfg.cfgTemplate) ? me.getConfigObject(cfg.cfgTemplate, me.initActionCfg(objId)) : {};

      sol.common.web.ActionHandler.execute(
        cfg.fct,
        cfgObject
      );
    },

    /**
     * Helps in executing advanced actions that include precondition checks and
     * different object types.
     *
     * Advanced action configurations are handled in the following order:
     *
     * 1.  select types (optional)
     * 2.  check preconditions (type selection possible if returned by check) (optional)
     * 3.  select target (optional)
     * 4.  execute action (IX/ AS) (required)
     *
     * Please note that step 1 and 2 can be used for selecting types. If a special function
     * is used for type selection (Step 1), the user selection is overriden if a second
     * type selection is handled by step 2.
     *
     *     {
     *       preconditions: {
     *         fct: 'RF_sol_contact_service_CheckContactPreconditions',
     *       },
     *       fct: 'RF_sol_contact_action_CreateContact',
     *       cfgTemplate: '{
     *              "parentId": "{{objId}}",
     *              "contactType": "{{type.name}},
     *              "templateId": "{{type.objId}}
     *       }',
     *       locale: {
     *           errorDlgTitle: locale['sol.contact.client.contact.create.dialog.error.title'],
     *           typesDlgTitle: locale['sol.contact.client.contact.create.dialog.title'],
     *           typesDlgHeader: locale['sol.contact.client.contact.create.dialog.header'],
     *           typesDlgText: locale['sol.contact.client.contact.create.dialog.text'],
     *           typesDlgNoTypes: locale['sol.contact.client.contact.create.msg.notype'],
     *
     *           targetDlgTitle: locale['sol.contact.client.contact.create.dialog.title'],
     *           targetDlgHeader: locale['sol.contact.client.contact.create.dialog.header'],
     *           targetDlgText: locale['sol.contact.client.contact.create.dialog.text'],
     *       }
     *     }
     *
     * @param {String} objId
     * @param {Object} cfg
     */
    executeAdvancedAction: function (objId, cfg) {
      var me = this,
          actionCfg = me.initActionCfg(objId),
          handler_selectTypes, handler_preconditions, handler_selectTarget, handler_executeAction;

      elo.helpers.Console.info("[sol.common.web.ActionHelper] executing advanced action on objId: " + objId, cfg);

      if (!cfg || !cfg.fct || !cfg.cfgTemplate) {
        throw "executing an advanced action requires mandatory config properties.";
      }

      // asynchronous calls require synchonisation between ajax responses.
      // therefore several handlers are linked.
      handler_selectTypes = function (objId, cfg, actionCfg) {
        if (cfg.selectType && cfg.selectType.fct) {
          // action requires precondition checks
          me.handleTypeSelection(objId, cfg, actionCfg, function (objId, cfg, actionCfg) {
            // preconditions handled
            handler_preconditions(objId, cfg, actionCfg);
          });
        } else {
          handler_preconditions(objId, cfg, actionCfg);
        }
      };
      handler_preconditions = function (objId, cfg, actionCfg) {
        if (cfg.preconditions && cfg.preconditions.fct) {
          // action requires precondition checks
          me.handlePrecondition(objId, cfg, actionCfg, function (objId, cfg, actionCfg) {
            // preconditions handled
            handler_selectTarget(objId, cfg, actionCfg);
          });
        } else {
          handler_selectTarget(objId, cfg, actionCfg);
        }
      };
      handler_selectTarget = function (objId, cfg, actionCfg) {
        if (cfg.selectTree) {
          me.handleTreeSelection(objId, cfg, actionCfg, function (objId, cfg, actionCfg) {
            handler_executeAction(objId, cfg, actionCfg);
          });
        } else {
          handler_executeAction(objId, cfg, actionCfg);
        }
      };
      handler_executeAction = function (objId, cfg, actionCfg) {
        me.handleExecuteAction(objId, cfg, actionCfg);
      };

      // call first handler
      handler_selectTypes(objId, cfg, actionCfg);
    },

    /**
     * @private
     * handles precondition checks for advanced actions.
     * @param {String} objId
     * @param {Object} cfg
     * @param {Object} actionCfg
     * @param {Object} readyFct
     */
    handlePrecondition: function (objId, cfg, actionCfg, readyFct) {
      var me = this;

      sol.common.IxUtils.execute(cfg.preconditions.fct, {
        targetId: objId
      }, function (checkResult) {
        // sucess
        elo.helpers.Console.info("[sol.common.web.ActionHelper] prepare action successful.", checkResult);

        if (checkResult.valid !== true) {
          elo.helpers.Console.info("[sol.common.web.ActionHelper] prepare action returned invalid result. Cancel execution.");
          api.Webclient.alert(cfg.locale.errorDlgTitle || locales["sol.common.client.ActionHandler.errordlg.title"], checkResult.msg);
          return;
        }

        if (checkResult.targetId && checkResult.targetId != objId) {
          elo.helpers.Console.info("[sol.common.web.ActionHelper] changed objId by preconditions to: " + checkResult.targetId);
          objId = checkResult.targetId;
        }

        actionCfg.objId = objId;
        actionCfg.preconditions = checkResult;

        if (checkResult.types && checkResult.types.length >= 0) {
          me.handleSimpleActionTypes(checkResult.types, objId, cfg, actionCfg, function (objId, cfg, actionCfg) {
            // call ready
            readyFct(objId, cfg, actionCfg);
          });
        } else {
          // call ready
          readyFct(objId, cfg, actionCfg);
        }
      }, function (error) {
        elo.helpers.Console.error("[sol.common.web.ActionHelper] prepare action returned an unexpected error.", error);
        api.Webclient.alert(cfg.locale.errorDlgTitle || locales["sol.common.client.ActionHandler.errordlg.title"], error.msg + ": " + error.details);
      });
    },

    /**
     * @private
     * handles simple selection of different types.
     * @param {String} types
     * @param {String} objId
     * @param {Object} cfg
     * @param {Object} actionCfg
     * @param {Object} readyFct
     */
    handleSimpleActionTypes: function (types, objId, cfg, actionCfg, readyFct) {
      var choices, type, i;

      if (types && types.length > 1) {
        choices = [], type;
        for (i = 0; i < types.length; i++) {
          type = types[i];
          choices.push({ title: type.name, text: type.desc, data: type });
        }

        elo.helpers.Console.info("[sol.common.web.ActionHelper] prepare action returned multiple type choices.", choices);
        api.Webclient.showCommandLinkDialog(
          cfg.locale.typesDlgTitle,
          cfg.locale.typesDlgHeader,
          cfg.locale.typesDlgText,
          choices,
          function (choice) { // selected type
            actionCfg.type = choice.data;
            // call ready
            readyFct(objId, cfg, actionCfg);
          }, function () {    // clicked cancel
            elo.helpers.Console.info("[sol.common.web.ActionHelper] closed file selection dialog. cancel execution.");
          }
        );
      } else if (types && types.length > 0) {
        actionCfg.type = types[0];
        // call ready
        readyFct(objId, cfg, actionCfg);
      } else {
        api.Webclient.alert(cfg.locale.typesDlgTitle || locales["sol.common.client.ActionHandler.errordlg.title"], cfg.locale.typesDlgNoTypes);
      }
    },

    handleTypeSelection: function (objId, cfg, actionCfg, readyFct) {
      var me = this,
          typeServiceCfg = {};

      if (cfg.selectType && cfg.selectType.cfgTemplate) {
        typeServiceCfg = me.getConfigObject(cfg.selectType.cfgTemplate, actionCfg);
      }

      sol.common.IxUtils.execute(cfg.selectType.fct, typeServiceCfg, function (types) {
        // sucess
        me.handleSimpleActionTypes(types, objId, cfg, actionCfg, readyFct);
      }, function (error) {
        elo.helpers.Console.error("[sol.common.web.ActionHelper] prepare action returned an unexpected error.", error);
        api.Webclient.alert(cfg.locale.errorDlgTitle || locales["sol.common.client.ActionHandler.errordlg.title"], error.msg + ": " + error.details);
      });
    },

    handleTreeSelection: function (objId, cfg, actionCfg, readyFct) {
      var me = this,
          rootId = 1;

      if (cfg.selectTree.root) {
        rootId = elo.IX.ix().checkoutSord(cfg.selectTree.root, elo.CONST.SORD.mbOnlyId, elo.CONST.LOCK.NO).id;
      } else if (cfg.selectTree.rootFromCfgFile && cfg.selectTree.rootFromCfgProperty) {
        sol.common.IxUtils.execute("RF_sol_common_service_GetConfig", {
          objId: cfg.selectTree.rootFromCfgFile
        }, function (cfgResult) {
          // set root id and recall handleTreeSelection
          try {
            cfg.selectTree.root = me.getConfigObject(cfg.selectTree.rootFromCfgProperty, cfgResult);
            me.handleTreeSelection(objId, cfg, actionCfg, readyFct);
          } catch (msg) {
            api.Webclient.alert(locales["sol.common.client.ActionHandler.errordlg.title"], "Invalid configuration for tree selection. rootFromCfgProperty should return a valid json object. " + msg);
          }
        }, function (err) {
          //console.error(o);
        });
        return;
      }

      elo.helpers.Console.info("[sol.common.web.ActionHelper] action requires target selection. Using root: " + rootId);

      api.Webclient.showTreeSelectDialog(
        cfg.locale.treeDlgTitle || "",
        cfg.locale.treeDlgHeader || "",
        rootId,
        cfg.locale.treeDlgRootName || "..",
        function (selection) {
          // selected target
          actionCfg.tree = {
            name: selection.name,
            objId: selection.id
          };
          // call ready
          readyFct(objId, cfg, actionCfg);
        },
        function () {
          // canceled
        }
      );
    },

    prepareCfgObj: function (cfgTemplate, actionCfg) {
      var cfgObj, regex, objIdReplacement;

      cfgTemplate = cfgTemplate.replace(/\\{{/g, "{{");
      if (cfgTemplate.indexOf("\"{{objId}}\"") > -1) {
        regex = new RegExp("\"{{objId}}\"", "g");
        objIdReplacement = (actionCfg.objId) ? "\"" + actionCfg.objId + "\"" : null;
      } else {
        regex = new RegExp("{{objId}}", "g");
        objIdReplacement = (actionCfg.objId) ? actionCfg.objId : null;
      }
      cfgTemplate = cfgTemplate.replace(regex, objIdReplacement);

      cfgObj = cfgTemplate ? JSON.parse(cfgTemplate) : {};

      cfgObj.$templating = { $type: actionCfg.type, $tree: actionCfg.tree, $preconditions: actionCfg.preconditions };

      return cfgObj;
    },

    /**
     * @private
     * handles the final execution of the action.
     * @param {String} objId
     * @param {Object} cfg
     * @param {Object} actionCfg
     */
    handleExecuteAction: function (objId, cfg, actionCfg) {
      var me = this, cfgObj;

      cfgObj = me.prepareCfgObj(cfg.cfgTemplate, actionCfg);  // render objId and setup serverside templating data

      switch (cfg.type) {
        case "AS":
          sol.common.web.ActionHandler.executeAs(cfg.solution, cfg.fct, cfgObj);
          break;
        default:
          sol.common.web.ActionHandler.execute(cfg.fct, cfgObj);
      }
    },

    initActionCfg: function (objId) {
      var actionCfg = { objId: objId };
      return actionCfg;
    },

    getConfigObject: function (cfgTemplate, data) {
      var str = Handlebars.compile(cfgTemplate)(data);
      return JSON.parse(str);
    }

  });


  /**
   * This class provides utility functions to call IX or AS functions and handle the response in a standardized way.
   *
   * @eloweb
   * @requires sol.common.IxUtils
   */
  sol.define("sol.common.web.ActionHandler", {
    singleton: true,

    /**
     * Executes a IX registered function and handles the response in a standardized way.
     *
     * If spezial handling is needed a custom callback can be spezified as parameter.
     * This callback get's the result Object of the registered function as only parameter.
     *
     * @param {String} registeredFunctionName
     * @param {Object} params (optional) The configuration object which will be send to the registered function
     * @param {Function} callback (optional) Should not be used anymore
     * @param {String} loadingMessage (optional) Message that is displayed while performing async operations.
     */
    execute: function (registeredFunctionName, params, callback, loadingMessage) {
      var me = this;

      me.showLoadingIndicator(loadingMessage);
      sol.common.IxUtils.execute(registeredFunctionName, params, function (resultObj) {
        if (callback && Object.prototype.toString.call(callback) === "[object Function]") {
          me.logger.warn("Use of 'callback' parameter is depricated and therefore not recommended.");
          callback.call(me, resultObj);
          me.hideLoadingIndicator();
          return;
        }
        if (resultObj) {
          me.handleEvents(resultObj.events);
          // loading indicator is hidden by event handler
        } else {
          me.hideLoadingIndicator();
        }
      }, function (err) {
        me.hideLoadingIndicator();
        // error
        var msg = "";
        if (err && err.msg) {
          msg = err.msg;
        }
        api.Webclient.alert(locales["sol.common.client.ActionHandler.errordlg.title.unexpected"], msg);
      });
    },

    executeAs: function (solutionName, asRuleName, params, callback, loadingMessage) {
      var me = this;

      me.showLoadingIndicator(loadingMessage);
      sol.common.IxUtils.execute("RF_sol_common_service_ExecuteAsAction", {
        solution: solutionName,
        action: asRuleName,
        config: params,
        connParams: {
          language: elo.IX.getLoginResult().clientInfo.language
        }
      }, function (resultObj) {
        if (resultObj && resultObj.content) {
          try {
            resultObj = JSON.parse(resultObj.content);
          } catch (ex) {
            if (!resultObj.events) {
              console.error(resultObj);
              me.hideLoadingIndicator();
              api.Webclient.alert(locales["sol.common.client.ActionHandler.errordlg.title.unexpected"], locales["sol.common.client.ActionHandler.errordlg.msg.unexpected"]);
              return;
            }
          }
        }
        if (resultObj && resultObj.events && resultObj.events.length > 0 && resultObj.events[0].ID && resultObj.events[0].ID === "ERROR") {
          // handle IX Exceptions
          console.error(resultObj);
          me.hideLoadingIndicator();
          if (resultObj.events[0].obj && resultObj.events[0].obj.msg) {
            var error = resultObj.events[0].obj.msg;
            api.Webclient.alert(locales["sol.common.client.ActionHandler.errordlg.title.unexpected"], error);
          }
          return;
        }
        if (callback && Object.prototype.toString.call(callback) === "[object Function]") {
          me.logger.warn("Use of 'callback' parameter is depricated and therefore not recommended.");
          callback.call(me, resultObj);
          me.hideLoadingIndicator();
          return;
        }
        if (resultObj && resultObj.events) {
          me.handleEvents(resultObj.events);
          // loading indicator is hidden by event handler
        } else {
          me.hideLoadingIndicator();
        }
      }, function (err) {
        // error
        api.Webclient.alert(locales["sol.common.client.ActionHandler.errordlg.title.unexpected"], locales["sol.common.client.ActionHandler.errordlg.msg.unexpected"]);
        console.error(err);
        me.hideLoadingIndicator();
      });
    },

    /**
     * @private
     * Handler for events passed by an Action. This function is called recursively for all events since event
     * handlers might perform async operations.
     * @param {Object} events
     * @param {Object} context
     */
    handleEvents: function (events, context) {
      var me = this,
          eventTypes = sol.common.IxUtils.CONST.EVENT_TYPES,
          event, handler;

      context = context || { dirtySord: true, dirtyWfStatus: true };

      if (events && events.length > 0) {
        event = events.shift();

        if (!me.checkExecution(event, context)) {
          me.handleEvents(events, context);
          return;
        }

        switch (event.ID) {
          case eventTypes.REFRESH:
            handler = sol.create("sol.common.web.ActionHandler.Refresh");
            me.hideLoadingIndicator();
            break;
          case eventTypes.GOTO:
            handler = sol.create("sol.common.web.ActionHandler.Goto");
            me.hideLoadingIndicator();
            break;
          case eventTypes.DIALOG:
            handler = sol.create("sol.common.web.ActionHandler.Dialog", {
              actionHandler: me,
              hideLoadingIndicator: me.hideLoadingIndicator
            });
            // loading indicator is hidden by Action Handler
            break;
          case eventTypes.ACTION:
            handler = sol.create("sol.common.web.ActionHandler.Action", {
              actionHandler: me,
              hideLoadingIndicator: me.hideLoadingIndicator
            });
            // loading indicator is hidden by Action Handler
            break;
          case eventTypes.FEEDBACK:
            handler = sol.create("sol.common.web.ActionHandler.Feedback");
            me.hideLoadingIndicator();
            break;
          case eventTypes.ERROR:
            handler = sol.create("sol.common.web.ActionHandler.Error");
            me.hideLoadingIndicator();
            break;
          default:
        }

        if (handler && me.isFunction(handler.execute)) {
          handler.execute(event, context, function () {
            me.handleEvents(events, context);
          });
        } else {
          me.logger.warn(["No handler for event of type '{0}'", event.ID]);
        }
      } else {
        me.hideLoadingIndicator();
      }
    },

    /**
     * @private
     * @param {Object} event
     * @param {Object} context
     * @return {Boolean}
     */
    checkExecution: function (event, context) {
      var me = this,
          checkValue, mapitems;

      if (event.ON) {
        if (context.dirtySord && event.ON.objId) {
          context.sord = elo.IX.ix().checkoutSord(event.ON.objId, elo.CONST.SORD.mbAllIndex, elo.CONST.LOCK.NO);
          context.dirtySord = false;
        }

        if (context.dirtyWfStatus && event.ON.flowId) {
          context.wfStatus = sol.common.IxUtils.execute("RF_sol_common_service_GetWorkflowMetadata", { flowId: event.ON.flowId }).status;
          context.dirtyWfStatus = false;
        }

        switch (event.ON.type) {
          case "WF_STATUS":
            checkValue = context.wfStatus;
            break;
          case "GRP":
            checkValue = context.sord.getLineByGroup(event.ON.key);
            break;
          case "SORD":
            checkValue = context.sord[event.ON.key];
            break;
          case "MAP":
            mapitems = elo.IX.ix().checkoutMap(elo.CONST.MAP_CONFIG.DOMAIN_SORD, event.ON.objId, [event.ON.key], elo.CONST.LOCK.NO).items;
            if (mapitems && mapitems.length === 1) {
              checkValue = mapitems[0].value;
            }
            break;
          default:
            me.logger.warn(["event defines non existing ON.type={0}, ON condition will be ignored", event.ON.type]);
            return true;
        }

        return checkValue == event.ON.value;
      }
      return true;
    },

    /**
     * @private
     * @param {Object} obj
     * @return {Object}
     */
    isFunction: function (obj) {
      return obj && Object.prototype.toString.call(obj) === "[object Function]";
    },

    showLoadingIndicator: function (text) {
      var me = this;
      me.loadingIndicator = Ext.MessageBox.show({
        msg: text || "Loading...",
        //modal: false,
        width: 300,
        wait: true,
        waitConfig: { interval: 200 }
      });
    },

    hideLoadingIndicator: function () {
      var me = this;
      if (me.loadingIndicator) {
        me.loadingIndicator.hide();
      }
    }


  });

  sol.define("sol.common.web.ActionHandler.Refresh", {
    tryCheckoutTimes: 100,

    execute: function (event, context, callback) {
      var eventConfig;

      if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.REFRESH) {
        throw "'sol.common.jc.ActionHandler.REFRESH' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.REFRESH + "' events, but event-ID was '" + event.ID + "'";
      }

      if (event.obj) {
        eventConfig = event.obj;

        if (eventConfig.objId) {
          window.setTimeout(function () {
            api.Webclient.refreshView();
            callback.call(this);
          }, 1);
        }
      }
    }
  });

  sol.define("sol.common.web.ActionHandler.Goto", {
    tryCheckoutTimes: 100,

    execute: function (event, context, callback) {
      var me = this,
          eventConfig;

      if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.GOTO) {
        throw "'sol.common.jc.ActionHandler.GOTO' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.GOTO + "' events, but event-ID was '" + event.ID + "'";
      }

      if (event.obj) {
        eventConfig = event.obj;

        if (eventConfig.flowId && eventConfig.nodeId) {
          window.setTimeout(function () {
            // internal Web Client access
            api.Webclient.gotoTask({ flowId: Number(eventConfig.flowId), nodeId: Number(eventConfig.nodeId) });
            callback.call(this);
          }, 1);
        } else if (eventConfig.objId) {
          window.setTimeout(function () {
            // internal Web Client access
            api.Webclient.gotoEntry(Number(eventConfig.objId));
            if (eventConfig.checkout) {
              me.checkoutSord(eventConfig.objId, 0);
            }
            callback.call(this);
          }, 1);
        }
      }
    },

    checkoutSord: function (objId, times) {
      var me = this,
          sord;

      // internal Web Client access
      sord = elo.ModelRegistry.getDataInstance(elo.MainCtrl.modelNames.selectedSord);

      if (sord && Object.prototype.toString.call(sord) === "[object Array]") {
        sord = sord[0];
      }

      if (sord && sord.get && String(sord.get("id")) === String(objId)) {
        elo.EventRegistry.callBusEvent("BTN_EDITINOFFICE");
      } else if (times < me.tryCheckoutTimes) {
        window.setTimeout(function () {
          me.checkoutSord(objId, times + 1);
        }, 50);
      } else {
        console.error("Checkout document failed.");
      }
    }
  });

  sol.define("sol.common.web.ActionHandler.Dialog", {

    execute: function (event, context, callback) {
      var me = this,
          eventConfig;

      if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.DIALOG) {
        throw "'sol.common.web.ActionHandler.DIALOG' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.DIALOG + "' events, but event-ID was '" + event.ID + "'";
      }

      context.dirtySord = true;
      context.dirtyWfStatus = true;

      if (event.obj) {
        eventConfig = event.obj;
        if (eventConfig.url) {
          if (me.hideLoadingIndicator) {
            // prevent background flickering
            Ext.suspendLayouts();
            me.hideLoadingIndicator.call(me.actionHandler);
          }

          me.registerOpenWindow(event.obj.flowId, event.obj.nodeId);
          api.Webclient.showAppDialog(eventConfig.title || "", {
            url: eventConfig.url,
            doneHandler: function () {
              me.unregisterOpenWindow();
              callback.call(this);
            },
            closeHandler: function () {
              me.closeForm(event.obj.flowId, event.obj.nodeId);
              me.unregisterOpenWindow();
              callback.call(this);
            }
          });
          Ext.resumeLayouts();
        } else if (eventConfig.flowId && eventConfig.nodeId) {
          Ext.suspendLayouts();
          me.hideLoadingIndicator.call(me.actionHandler);

          me.registerOpenWindow(event.obj.flowId, event.obj.nodeId);
          api.Webclient.showAppDialog(eventConfig.title || "", {
            flowId: event.obj.flowId,
            nodeId: event.obj.nodeId,
            doneHandler: function () {
              me.unregisterOpenWindow();
              callback.call(this);
            },
            closeHandler: function () {
              me.closeForm(event.obj.flowId, event.obj.nodeId);
              me.unregisterOpenWindow();
              callback.call(this);
            }
          });
          Ext.resumeLayouts();
        } else {
          if (me.hideLoadingIndicator) {
            me.hideLoadingIndicator.call(me.actionHandler);
          }
          callback.call(me);
        }
      }
    },

    registerOpenWindow: function (flowId, nodeId) {
      var me = this;
      me.originalonunload = window.onbeforeunload;
      me.flowId = flowId;
      me.nodeId = nodeId;
      window.onbeforeunload = function () {
        me.closeForm(me.flowId, me.nodeId);
        if (me.originalonunload) {
          me.originalonunload();
        }
      };
      me.registeredWindow = true;
    },

    unregisterOpenWindow: function () {
      var me = this;
      if (me.registeredWindow) {
        window.onbeforeunload = me.originalonunload;
        me.flowId = null;
        me.nodeId = null;
        me.registeredWindow = false;
      }
    },

    /**
     * Aborts the current form if the user clicks cancel or reloads the page.
     * @param {Number} flowId
     * @param {Number} nodeId
     */
    closeForm: function (flowId, nodeId) {
      var me = this;
      if (me.registeredWindow && me.flowId && me.nodeId) {
        sol.common.IxUtils.execute("RF_sol_common_service_ActionCancelForm", {
          flowId: flowId, nodeId: nodeId
        }, function () {
          console.info("sol.common.client.ActionHandler: Closed open process.");
        }, function (error) {
          console.error("sol.common.client.ActionHandler: Closing open process failed.", error);
        });
      }
    }
  });

  sol.define("sol.common.web.ActionHandler.Error", {

    execute: function (event, context, callback) {
      var eventConfig;

      if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.ERROR) {
        throw "'sol.common.web.ActionHandler.ERROR' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.ERROR + "' events, but event-ID was '" + event.ID + "'";
      }

      if (event.obj) {
        eventConfig = event.obj;
        api.Webclient.alert(locales["sol.common.client.ActionHandler.errordlg.title"], eventConfig.msg);
      }

      callback.call(this);
    }
  });

  sol.define("sol.common.web.ActionHandler.Feedback", {

    execute: function (event, context, callback) {
      var eventConfig;

      if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.FEEDBACK) {
        throw "'sol.common.web.ActionHandler.FEEDBACK' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.FEEDBACK + "' events, but event-ID was '" + event.ID + "'";
      }

      setTimeout(function () {
        if (event.obj) {
          eventConfig = event.obj;
          if (eventConfig.permanent === true) {
            sol.common.web.ApiUtils.showInfoMessage(eventConfig.msg);
          } else {
            sol.common.web.ApiUtils.showPopupMessage(eventConfig.msg);
          }
        }
        callback.call(this);
      }, 0);
    }
  });

  sol.define("sol.common.web.ActionHandler.Action", {
    execute: function (event, context, callback) {
      if (event.ID !== sol.common.IxUtils.CONST.EVENT_TYPES.ACTION) {
        throw "'sol.common.web.ActionHandler.ACTION' can only handle '" + sol.common.IxUtils.CONST.EVENT_TYPES.ACTION + "' events, but event-ID was '" + event.ID + "'";
      }

      context.dirtySord = true;
      context.dirtyWfStatus = true;

      if (event.COMPONENT === sol.common.IxUtils.CONST.COMPONENTS.IX) {
        sol.common.web.ActionHandler.execute(event.obj.registeredFunction, event.obj.params);
      } else if (event.COMPONENT === sol.common.IxUtils.CONST.COMPONENTS.AS) {
        sol.common.web.ActionHandler.executeAs(event.obj.solution, event.obj.directRule, event.obj.params, null, "");
      }

      callback.call(this);
    }
  });

});

api.require({
  namespace: ["sol", "sol.common.web.BarcodeRegistry"],
  promise: new Promise(function (resolve, reject) {
    var any;
    try {
      any = new de.elo.ix.client.Any();
      any.type = elo.CONST.ANY.TYPE_STRING;
      any.stringValue = "{}";
      api.Webclient.getIXConnection().ix().executeRegisteredFunction("RF_sol_common_services_ActionDefinitionCollector", any, new de.elo.ix.client.AsyncCallback(function (successAnyResult) {
        // sucess
        sol.$actionDefinitionsLoaded = true;
        sol.$actionDefinitionCollectorResult = successAnyResult;
        resolve();
      }, function (ex) {
        // failure
        console.error("[sol.common.web.ActionDefinitionUtils] loading ribbon definition failed (async failure callback): " + ex);
        reject();
      }));
    } catch (e) {
      console.error("[sol.common.web.ActionDefinitionUtils] loading ribbon definition failed (promise error): " + e);
      reject();
    }
  })
}, function () {

/**
 * This class loads ELO Business Solutions action definitions and creates the ribbon, button groups and buttons.
 *
 * This class is automatically called during client startup.
 *
 * @requires sol.common.IxUtils
 */
  sol.define("sol.common.web.ActionDefinitionUtils", {
    singleton: true,

    TAB_CONST: {
      HOME: { name: "START", position: 1000 },
      DOCUMENT: { name: "EXTENDED", position: 2000 },
      ARCHIVE: {},
      VIEW: { name: "VIEW", position: 3000 },
      WORKFLOW: { name: "TASK", position: 4000 },
      INTRAY: {},
      SEARCH: { name: "SEARCH", position: 6000 }
    },

    STD_ICONS: {
      small: "sol-scriptbutton16",
      smallHighRes: "sol-scriptbutton16-200",
      big: "sol-scriptbutton32",
      bigHighRes: "sol-scriptbutton32-200"
    },

    /**
	   * Initializes ribbon buttons, groups and tabs for ELO Business Solutions.
	   * @param {Object} contect. The current script scope.
	   */
    initializeRibbon: function () {
      var me = this,
          any, anyResult, result;

      try {
        if (sol.$actionDefinitionsLoaded === true) {
          // use result of promise in current WebClient versions
          anyResult = sol.$actionDefinitionCollectorResult;
        } else {
          // force synchronous call -> fallback in case promises are not supoorted in WebClient version
          any = new de.elo.ix.client.Any();
          any.type = elo.CONST.ANY.TYPE_STRING;
          any.stringValue = "{}";
          anyResult = api.Webclient.getIXConnection().ix().executeRegisteredFunction("RF_sol_common_services_ActionDefinitionCollector", any);
        }

        result = JSON.parse((anyResult && anyResult.stringValue) ? String(anyResult.stringValue) : "{}");

        if (result && result.definitions) {
          me.buildRibbonFromDefinition(result.definitions);
        }
      } catch (e) {
        console.error("[sol.common.web.ActionDefinitionUtils] loading ribbon definition failed: " + e);
      }
    },

    /**
     * Builds the web client ribbon based on ribbon button/ group/ tab definitions given by RF_sol_common_services_ActionDefinitionCollector.
     * @private
     * @param {Object[]} defs action/ ribbon definition
     */
    buildRibbonFromDefinition: function (defs) {
      var me = this,
          i, j, k, def, localDef, group, button, tab, webclientStdTab,
          dpi = (elo && elo.data && elo.data.dpi) ? elo.data.dpi : 100,
          dynRibbon = {
            _buttons: {},
            buttons: [],
            _groups: {},
            groups: [],
            _tabs: {},
            tabs: []
          },
          groupsForStandardRibbons = [],
          addedGroupsForStandardRibbons = {},
          handler = function (def, objId) {
            switch (def.type) {
              case "ADVANCED_ACTION":
                sol.common.web.ActionHelper.executeAdvancedAction(objId, def.action);
                break;
              case "SIMPLE_ACTION":
                sol.common.web.ActionHelper.executeSimpleAction(objId, def.action);
                break;
              default:
                console.error("No handler found for ribbon definition", def);
            }
          },
          getLineByGroup = function (sord, group) {
            var i, objKeys = sord.get("objKeys");
            if (sord === null || objKeys === undefined) {
              return null;
            }
            for (i = 0; i < objKeys.length; i += 1) {
              if (objKeys[i].name === group && objKeys[i].data && objKeys[i].data.length > 0) {
                return objKeys[i].data[0];
              }
            }
            return null;
          },
          btnAccess = function (state) {
            var def = this.def,
                access = (!def.ribbon.button.access
                || ((def.ribbon.button.access.document ? state.hasSord() && !state.getSord().isFolder() : false)
                || (def.ribbon.button.access.folder ? state.hasSord() && state.getSord().isFolder() : false)
                || (!def.ribbon.button.access.folder && !def.ribbon.button.access.document)))
                && ((def.ribbon.button.access && def.ribbon.button.access.solTypes && def.ribbon.button.access.solTypes.length > 0 && state.hasSord())
                     ? def.ribbon.button.access.solTypes.indexOf(getLineByGroup(state.getSord(), "SOL_TYPE")) != -1 : true);
            return access;
          },
          btnHandler = function (state) {
            var def = this.def, sord;
            if (state.hasSord()) {
              sord = state.getSord();
            }
            handler(def, sord ? sord.get("id") : null);
          };
      for (i = 0; i < defs.length; i++) {
        def = defs[i];

        if (def.ribbon && def.ribbon.button && def.ribbon.ribbonTab && def.ribbon.buttongroup) {
          // create web client ribbon button
          dynRibbon._buttons[def.ribbon.button.name] = new api.Button({
            name: def.ribbon.button.name,
            def: def,
            access: btnAccess,
            handler: btnHandler,
            text: def.ribbon.button.text,
            splitText: def.ribbon.button.splitText,
            tooltipTitle: "<span class='title'>" + def.ribbon.button.text + "</span>",
            tooltipText: "<p>" + def.ribbon.button.tooltipText + "</p>",
            bigIconCls: (dpi > 150) ? (def.ribbon.button.web.bigIconHighRes || me.STD_ICONS.bigHighRes) : (def.ribbon.button.web.bigIcon || me.STD_ICONS.big),
            smallIconCls: (dpi > 150) ? (def.ribbon.button.web.smallIconHighRes || me.STD_ICONS.smallHighRes) : (def.ribbon.button.web.smallIcon || me.STD_ICONS.small),
            position: def.ribbon.button.position,
            asTile: !!def.ribbon.button.asTile,
            iconName: def.ribbon.button.web.iconName
          });
          me.logger.info("registered button: " + def.ribbon.button.name);
          dynRibbon.buttons.push(dynRibbon._buttons[def.ribbon.button.name]);

          webclientStdTab = me.TAB_CONST[def.ribbon.ribbonTab.name];

          // read ribbon tab if new
          if (!webclientStdTab && !dynRibbon._tabs[def.ribbon.ribbonTab.name]) {
            me.logger.info("new ribbon tab: " + def.ribbon.ribbonTab.name);
            dynRibbon._tabs[def.ribbon.ribbonTab.name] = {
              cfg: def.ribbon.ribbonTab,
              name: def.ribbon.ribbonTab.name,
              text: def.ribbon.ribbonTab.text,
              position: def.ribbon.ribbonTab.position,
              groups: [],                     // group names
              _groups: []                     // group definitions
            };
            dynRibbon.tabs.push(dynRibbon._tabs[def.ribbon.ribbonTab.name]);
          }

          // read ribbon group if new
          if (!dynRibbon._groups[def.ribbon.buttongroup.name]) {
            me.logger.info("new button group: " + def.ribbon.buttongroup.name);
            dynRibbon._groups[def.ribbon.buttongroup.name] = {
              cfg: def.ribbon.buttongroup,
              name: def.ribbon.buttongroup.name,
              text: def.ribbon.buttongroup.text,
              mode: def.ribbon.buttongroup.mode,
              buttons: [],                    // button names
              _buttons: []                    // button definitions
            };
            dynRibbon.groups.push(dynRibbon._groups[def.ribbon.buttongroup.name]);

            if (dynRibbon._tabs[def.ribbon.ribbonTab.name]) {
              // is dynamic tab
              dynRibbon._tabs[def.ribbon.ribbonTab.name]._groups.push();
              dynRibbon._tabs[def.ribbon.ribbonTab.name]._groups.push(dynRibbon._groups[def.ribbon.buttongroup.name]);
            } else if (webclientStdTab && webclientStdTab.name && webclientStdTab.position) {
              // expect web client tab
              groupsForStandardRibbons.push({
                def: def,
                stdTab: webclientStdTab
              });
            }
          }

          // register button in group
          if (dynRibbon._groups[def.ribbon.buttongroup.name]) {
            // is dynamic group
            dynRibbon._groups[def.ribbon.buttongroup.name]._buttons.push({
              def: def,
              btn: dynRibbon._buttons[def.ribbon.button.name]
            });
          } else {
            // expect web client group
            //         api.Registry.addRibbonButton(def.ribbon.button.name, def.ribbon.buttongroup.name, def.ribbon.button.position);
          }
        }

        // register barcode handlers
        if (def.barcode && def.barcode.identifier) {
          localDef = def;
          sol.common.web.BarcodeRegistry.register(def.barcode.identifier, def.action.fct,
          function (identifier, objId, data) {
            handler(localDef, objId);
          });
        }
      }

      // register groups
      for (j = 0; j < dynRibbon.groups.length; j++) {
        group = dynRibbon.groups[j];
        group._buttons = group._buttons.sort(function (a, b) {
          return a.def.ribbon.button.position > b.def.ribbon.button.position ? 1 : -1;
        });

        // add buttons to group
        for (k = 0; k < group._buttons.length; k++) {
          button = group._buttons[k];
          group.buttons.push(button.def.ribbon.button.name);
        }

        me.logger.info("registered button group: " + group.name);
        group._group = new api.ButtonGroup(group);
      }

      for (j = 0; j < groupsForStandardRibbons.length; j++) {
        var grpForStdtTab = groupsForStandardRibbons[j];
        if (grpForStdtTab.def && grpForStdtTab.stdTab && !addedGroupsForStandardRibbons[grpForStdtTab.def.ribbon.buttongroup.name]) {
          addedGroupsForStandardRibbons[grpForStdtTab.def.ribbon.buttongroup.name] = true;
          api.Registry.addButtonGroup(grpForStdtTab.def.ribbon.buttongroup.name, grpForStdtTab.stdTab.name, grpForStdtTab.def.ribbon.buttongroup.position * 100);
        }
      }

      // register tabs
      for (j = 0; j < dynRibbon.tabs.length; j++) {
        tab = dynRibbon.tabs[j];
        tab._groups = tab._groups.sort(function (a, b) {
          return a.cfg.position > b.cfg.position ? 1 : -1;
        });

        // add groups to tabs
        for (k = 0; k < tab._groups.length; k++) {
          group = tab._groups[k];
          tab.groups.push(group.name);
        }

        me.logger.info("registered tab: " + tab.name);
        tab._tab = new api.RibbonTab(tab);
        api.Registry.addRibbonTab(tab.name, tab.position * 100);
      }
    }
  });

  sol.common.web.ActionDefinitionUtils.initializeRibbon();
});

//# sourceURL=sol.common.web.js