"use strict";

module.exports = {
  replacer: function replacer(key, value) {
    if (typeof value === 'function') {
      return {
        type: 'JSFunction',
        value: String(value)
      };
    }
    return value;
  },
  isAsyncFunction: function isAsyncFunction(fn) {
    return fn[Symbol.toStringTag] === 'AsyncFunction';
  },
  reviewer: function reviewer(key, value) {
    if (!value) {
      return value;
    }
    if (key === 'icon') {
      if (typeof value === 'object') {
        return {
          type: 'smile',
          size: 'small'
        };
      }
    }
    if (typeof value === 'object') {
      if (value.type === 'JSFunction') {
        var _value = value.value && value.value.trim();
        var template = "\n          return function lowcode() {\n            const self = this;\n            try {\n              return (" + _value + ").apply(self, arguments);\n            } catch(e) {\n              console.log('call function which parsed by lowcode for key " + key + " failed: ', e);\n              return e.message;\n            }\n          };";
        try {
          return Function(template)();
        } catch (e) {
          if (e && e.message.includes("Unexpected token '{'")) {
            console.log('method need add funtion prefix');
            _value = 'function ' + _value;
            template = "\n            return function lowcode() {\n              const self = this;\n              try {\n                return (" + _value + ").apply(self, arguments);\n              } catch(e) {\n                console.log('call function which parsed by lowcode for key " + key + " failed: ', e);\n                return e.message;\n              }\n            };";
            return Function(template)();
          }
          console.error('parse lowcode function error: ', e);
          console.error(value);
          return value;
        }
      }
    }
    return value;
  },
  toJson: function toJson(object, replacer) {
    return JSON.stringify(object, replacer || this.replacer, 2);
  },
  parseJson: function parseJson(json) {
    var input = typeof json === 'string' ? json : JSON.stringify(json);
    return JSON.parse(input, this.reviewer);
  },
  calculateDependencies: function calculateDependencies(schema, componentsMap) {
    function findComps(schema, componentsMap, dependencies) {
      dependencies = dependencies || {};
      if (dependencies[schema.componentName]) {
        dependencies[schema.componentName].count++;
      } else {
        dependencies[schema.componentName] = {
          count: 1
        };
        if (componentsMap && componentsMap[schema.componentName]) {
          dependencies[schema.componentName].npm = componentsMap[schema.componentName]["package"];
          dependencies[schema.componentName].version = componentsMap[schema.componentName].version;
        }
      }
      if (schema.children && Array.isArray(schema.children)) {
        schema.children.forEach(function (child) {
          dependencies = Object.assign(dependencies, findComps(child, componentsMap, dependencies));
        });
      }
      return dependencies;
    }
    var comps = findComps(schema, componentsMap);
    var deps = {};
    Object.keys(comps).forEach(function (key) {
      var comp = comps[key];
      if (!comp.npm) comp.npm = 'BuiltIn';
      if (deps["" + comp.npm + (comp.version ? '@' + comp.version : '')]) {
        deps["" + comp.npm + (comp.version ? '@' + comp.version : '')][key] = comp.count;
      } else {
        var _deps;
        deps["" + comp.npm + (comp.version ? '@' + comp.version : '')] = (_deps = {}, _deps[key] = comp.count, _deps);
      }
    });
    return deps;
  }
};