//@include lib_Class.js
//@include lib_sol.common.DateUtils.js
//@include lib_sol.common.SordUtils.js
//@include lib_sol.common.Template.js
//@include sol.common.ix.services.GetNamespacedConfigs.js

/**
 * Utility methods for the monitoring modul.
 *
 * @author ELO Digital Office GmbH
 * @version 1.02.001
 *
 * @eloix
 * @requires moment
 * @requires sol.commom.SordUtils
 * @requires sol.common.DateUtils
 * @requires sol.common.TemplateUtils
 * @requires sol.common.ix.services.GetNamespacedConfigs
 */
sol.define("sol.common_monitoring.ix.TimedEventUtils", {
  logger: sol.create("sol.Logger", { scope: "sol.common_monitoring.ix.TimedEventUtils" }),

  singleton: true,

  getInjections: function (config) {
    if (config.configPath && config.configName) {
      return (config.configPath && config.configName)
        ? {
          $configRelation: { config: config.configPath },
          inject: { config: { config: "config", prop: config.configName, template: true } }
        }
        : null;
    }
  },

  getError: function (message, args) {
    return {
      hasError: true,
      error: {
        message: message,
        args: args || {}
      }
    };
  },

  optimizedExecute: function (self, requestParameters) {
    var me = this;
    try {
      return sol.common.IxUtils.optimizedExecute(
        requestParameters.provider,
        requestParameters.params,
        (self._optimize = self._optimize || {}),
        requestParameters.optimize,
        requestParameters.output
      );
    } catch (error) {
      me.logger.info("could not execute request", requestParameters);
      return null;
    }
  },

  translateMap: function (map) {
    return Object.keys(map)
      .map(function (key) {
        return {
          key: key,
          value: sol.common_monitoring.ix.TimedEventUtils.translateKey(map[key])
        };
      })
      .reduce(function (acc, keyValue) {
        acc[keyValue.key] = keyValue.value;
        return acc;
      }, {});
  },

  translateKey: function (key) {
    sol.common.TranslateTerms.require(key);
    return sol.common.TranslateTerms.translate(key);
  },

  setTimedEventDate: function (entry, params) {
    var dateEntry = sol.common.ObjectUtils.clone(entry),
        shift = sol.common.TemplateUtils.render(params.config.shift, params),
        date = (dateEntry.value == "{{now}}")
          ? sol.common.DateUtils.nowIso()
          : sol.common_monitoring.ix.TimedEventUtils.renderParams(dateEntry.value || "", params);

    dateEntry.value = sol.common_monitoring.ix.TimedEventUtils.shiftIso(date, shift) || dateEntry.value;

    return dateEntry;
  },

  shiftIso: function (isoDate, shift) {
    var date,
        shiftedIsoDate,
        fillString = "00000000000000";

    if (isoDate.length < fillString.length) {
      isoDate += fillString.substr(isoDate.length);
    }

    try {
      date = sol.common.DateUtils.shift(
        sol.common.DateUtils.isoToDate(isoDate + ""),
        shift.value,
        { unit: shift.unit }
      );
      shiftedIsoDate = sol.common.DateUtils.dateToIso(date);
    } catch (_e) {
      return null;
    }

    return shiftedIsoDate;
  },

  mapUpdateEntriesToKeys: function (entries, keyPrefix) {
    return (entries || [])
      .filter(function (entry) {
        return !(entry.key || "").indexOf(keyPrefix) == 0;
      })
      .map(function (entry) {
        return {
          key: keyPrefix + entry.type + "_" + entry.key,
          type: "MAP",
          value: entry.value
        };
      });
  },

  mapUpdateKeysToEntries: function (mapKeys, keyPrefix) {
    return Object.keys(mapKeys || {})
      .map(function (key) {
        return { key: key, value: mapKeys[key] };
      })
      .filter(function (mapEntry) {
        return (mapEntry.key || "").indexOf(keyPrefix) == 0;
      })
      .map(function (mapEntry) {
        var keyParts = (mapEntry.key || "")
          .substr(keyPrefix.length)
          .split("_");
        return {
          type: keyParts.shift(),
          key: keyParts.join("_"),
          value: mapEntry.value
        };
      });
  },

  getTemplateSord: function (sordId) {
    var sord,
        templateSord;

    if (sordId) {
      sord = sol.common.RepoUtils.getSord(sordId);

      templateSord = sord
        ? sol.common.ObjectFormatter.format({
          sord: {
            formatter: "sol.common.ObjectFormatter.TemplateSord",
            data: sord,
            config: {
              sordKeys: ["id", "guid", "maskName", "name", "desc", "IDateIso", "XDateIso", "ownerName"],
              allMapFields: true
            }
          }
        })
        : null;
    }

    return templateSord;
  },

  renderRequestParams: function (requestParams, params, isRerender) {
    return sol.common_monitoring.ix.TimedEventUtils.renderParams(requestParams, params, isRerender);
  },

  renderParams: function (requestParams, params, isRerender) {
    var renderedParams;
    if (!sol.common_monitoring.ix.TimedEventUtils.hasHandlebarExpression(requestParams)) {
      return requestParams;
    }

    renderedParams = sol.common.TemplateUtils.render(requestParams, params, { emptyNonRendered: isRerender });

    return isRerender
      ? renderedParams
      : sol.common_monitoring.ix.TimedEventUtils.renderParams(renderedParams, params, true);
  },

  hasHandlebarExpression: function (template) {
    return JSON.stringify(template).indexOf("{{") != -1;
  },

  getTimedEventDirectly: function (params) {
    return (params.timedEvent && params.timedEvent.id)
      ? params.timedEvent
      : null;
  },

  getTimedEventFromId: function (params) {
    return (params.id)
      ? (sol.common_monitoring.ix.TimedEventUtils.getTemplateSord(params.id) || {}).sord
      : null;
  },

  getSourceDirectly: function (params) {
    return (params.source && params.source.id)
      ? params.source
      : null;
  },

  getSourceFromSourceId: function (params) {
    return (params.sourceId)
      ? (sol.common_monitoring.ix.TimedEventUtils.getTemplateSord(params.sourceId) || {}).sord
      : null;
  },

  getTimedEventConfigDirectly: function (params) {
    return params.timedEventConfig;
  },

  getAndCacheTimedEventConfigByParams: function (params, cache) {
    var configs,
        configParams = sol.common.ObjectUtils.clone(params);

    configParams.configId = sol.common_monitoring.ix.TimedEventUtils.getConfigId(configParams);
    configParams.configNamespace = sol.common_monitoring.ix.TimedEventUtils.getConfigNamespace(configParams);

    configs = sol.common_monitoring.ix.TimedEventUtils.getAndCacheTimedEventConfigs(configParams, cache);
    return sol.common_monitoring.ix.TimedEventUtils.getTimedEventConfigFromConfigs(configs, configParams);
  },

  getTimedEventConfigFromConfigs: function (configs, params) {
    var configId,
        configNamespace,
        config;

    if (!configs) {
      return null;
    }

    configId = sol.common.TemplateUtils.render(params.configId, params);

    if (configs[configId]) {
      config = configs[configId];
    } else {
      configNamespace = sol.common.TemplateUtils.render(params.configNamespace, params);

      if (configs[configNamespace] && configs[configNamespace][configId]) {
        config = configs[configNamespace][configId];
      }
    }
    return config
      ? sol.common.ObjectUtils.clone(config)
      : null;
  },

  getConfigId: function (params) {
    return sol.common_monitoring.ix.TimedEventUtils.getConfigIdDirectly(params)
      || sol.common_monitoring.ix.TimedEventUtils.getConfigIdFromTimedEvent(params);
  },

  getConfigIdDirectly: function (params) {
    return params.configId;
  },

  getConfigIdFromTimedEvent: function (params) {
    return sol.common.TemplateUtils
      .render(
        sol.common.ObjectUtils.getProp(params, "timedEvent.mapKeys.UPDATE_GRP_TIMED_EVENT_CONFIG_ID"),
        params
      )
      || sol.common.ObjectUtils.getProp(params, "timedEvent.objKeys.TIMED_EVENT_CONFIG_ID");
  },

  getConfigNamespace: function (params) {
    return sol.common_monitoring.ix.TimedEventUtils.getConfigNamespaceDirectly(params)
      || sol.common_monitoring.ix.TimedEventUtils.getConfigNamespaceFromTimedEvent(params);
  },

  getConfigNamespaceDirectly: function (params) {
    return params.configNamespace;
  },

  getConfigNamespaceFromTimedEvent: function (params) {
    return sol.common.TemplateUtils
      .render(
        sol.common.ObjectUtils.getProp(params, "timedEvent.mapKeys.UPDATE_GRP_TIMED_EVENT_CONFIG_NAMESPACE"),
        params
      )
      || sol.common.ObjectUtils.getProp(params, "timedEvent.objKeys.TIMED_EVENT_CONFIG_NAMESPACE");
  },

  getAndCacheTimedEventConfigs: function (params, cache) {
    var configs;

    configs = sol.common_monitoring.ix.TimedEventUtils.getTimedEventConfigs(params, cache);
    if (!configs) {
      return null;
    }
    sol.common_monitoring.ix.TimedEventUtils.setTimedEventConfigsToCache(configs, cache);

    return configs;
  },

  getTimedEventConfigs: function (params, cache) {
    return sol.common_monitoring.ix.TimedEventUtils.getTimedEventConfigsDirectly(params)
      || sol.common_monitoring.ix.TimedEventUtils.getTimedEventConfigsFromCache(cache)
      || sol.common_monitoring.ix.TimedEventUtils.getTimedEventConfigsFromService(params);
  },

  getTimedEventConfigsFromCache: function (cache) {
    return (cache || {}).timedEventConfigs;
  },

  setTimedEventConfigsToCache: function (configs, cache) {
    cache = cache || {};
    cache.timedEventConfigs = configs;
  },

  getTimedEventConfigsDirectly: function (params) {
    return params.timedEventConfigs;
  },

  getTimedEventConfigsFromService: function (params) {
    return sol.create("sol.common.ix.services.GetNamespacedConfigs", {
      paths: (params || {}).timedEventConfigPaths || [],
      allSolutions: true
    }).process();
  }
});