'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _nodeBits = require('node-bits');

var _pluralize = require('pluralize');

var _pluralize2 = _interopRequireDefault(_pluralize);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

var mapListFieldSource = function mapListFieldSource(key, schemaConfig, modelConfig) {
  var reference = key;
  var field = key;

  switch (modelConfig.source.type) {
    case _nodeBits.MANY_TO_MANY:
    case _nodeBits.ONE_TO_MANY:
      reference = _pluralize2.default.singular(key);
      break;

    case _nodeBits.ONE_TO_ONE:
    case _nodeBits.MANY_TO_ONE:
      reference = key.replace('Id', '');
      field = reference;
      break;

    default:
      break;
  }

  return _extends({
    reference: reference,
    referenceKey: 'id',
    referenceDisplay: 'name',
    referenceField: field

  }, modelConfig.source);
};

var mapField = function mapField(key, schemaConfig, modelConfig) {
  if (modelConfig.type === _nodeBits.LIST) {
    modelConfig.source = mapListFieldSource(key, schemaConfig, modelConfig);
  }

  return _extends({
    mode: _nodeBits.READ_WRITE

  }, schemaConfig, modelConfig);
};

var mapFields = function mapFields(keys, schema, configMap) {
  return _lodash2.default.reduce(keys, function (result, key) {
    var schemaConfig = schema[key];
    var modelConfig = configMap[key] || {};
    return _extends({}, result, _defineProperty({}, key, mapField(key, schemaConfig, modelConfig)));
  }, {
    id: {
      mode: _nodeBits.HIDDEN
    }
  });
};

var mapSchema = function mapSchema(schema, models) {
  return _lodash2.default.reduce(schema, function (result, value, key) {

    var config = _lodash2.default.find(models, function (m) {
      return m.model === key;
    });

    if (!config) {
      return [].concat(_toConsumableArray(result), [{
        model: key,
        mode: _nodeBits.READ_WRITE,
        pluralizeTitle: true,
        map: mapFields(_lodash2.default.keys(value), value, {}),
        order: _lodash2.default.keys(value)
      }]);
    }

    if (config.mode === _nodeBits.HIDDEN) {
      return result;
    }

    var configMap = config.map || {};
    var allKeys = _lodash2.default.uniq([].concat(_toConsumableArray(_lodash2.default.keys(value)), _toConsumableArray(_lodash2.default.keys(configMap))));
    var order = config.order || allKeys;

    return [].concat(_toConsumableArray(result), [_extends({
      pluralizeTitle: true
    }, config, {
      map: mapFields(order, value, configMap),
      order: order
    })]);
  }, []);
};

exports.default = function (config) {
  var apiRoot = config.root || '/api';
  return {
    verb: _nodeBits.GET,
    route: apiRoot + '/schema_info',
    implementation: {
      get: function get(req, res) {
        var result = _lodash2.default.reduce(config.schema, function (result, value) {
          return [].concat(_toConsumableArray(result), _toConsumableArray(mapSchema(value.schema, config.models)));
        }, []);

        res.json(result);
      }
    }
  };
};