"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _lodash = _interopRequireDefault(require("lodash"));
var _utils = require("./utils");
var _config = require("../model_structure/config");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
var DbmlExporter = /*#__PURE__*/function () {
  function DbmlExporter() {
    _classCallCheck(this, DbmlExporter);
  }
  _createClass(DbmlExporter, null, [{
    key: "hasWhiteSpace",
    value: function hasWhiteSpace(str) {
      return /\s/g.test(str);
    }
  }, {
    key: "hasSquareBracket",
    value: function hasSquareBracket(str) {
      return /\[|\]/.test(str);
    }
  }, {
    key: "isExpression",
    value: function isExpression(str) {
      return /\s*(\*|\+|-|\([A-Za-z0-9_]+\)|\(\))/g.test(str);
    }
  }, {
    key: "escapeNote",
    value: function escapeNote(str) {
      return str.replaceAll("'", "\\'");
    }
  }, {
    key: "exportEnums",
    value: function exportEnums(enumIds, model) {
      var enumStrs = enumIds.map(function (enumId) {
        var _enum = model.enums[enumId];
        var schema = model.schemas[_enum.schemaId];
        return "Enum ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(_enum.name, "\" {\n").concat(_enum.valueIds.map(function (valueId) {
          return "  \"".concat(model.enumValues[valueId].name, "\"").concat(model.enumValues[valueId].note ? " [note: '".concat(DbmlExporter.escapeNote(model.enumValues[valueId].note), "']") : '');
        }).join('\n'), "\n}\n");
      });
      return enumStrs.length ? enumStrs.join('\n') : '';
    }
  }, {
    key: "getFieldLines",
    value: function getFieldLines(tableId, model) {
      var table = model.tables[tableId];
      var lines = table.fieldIds.map(function (fieldId) {
        var field = model.fields[fieldId];
        var schemaName = '';
        if (field.type.schemaName && field.type.schemaName !== _config.DEFAULT_SCHEMA_NAME) {
          schemaName = DbmlExporter.hasWhiteSpace(field.type.schemaName) ? "\"".concat(field.type.schemaName, "\".") : "".concat(field.type.schemaName, ".");
        }
        var line = "\"".concat(field.name, "\" ").concat(schemaName).concat(DbmlExporter.hasWhiteSpace(field.type.type_name) || DbmlExporter.hasSquareBracket(field.type.type_name) ? "\"".concat(field.type.type_name, "\"") : field.type.type_name);
        var constraints = [];
        if (field.unique) {
          constraints.push('unique');
        }
        if (field.pk) {
          constraints.push('pk');
        }
        if (field.not_null) {
          constraints.push('not null');
        }
        if (field.increment) {
          constraints.push('increment');
        }
        if (field.dbdefault) {
          var value = 'default: ';
          switch (field.dbdefault.type) {
            case 'boolean':
            case 'number':
              value += "".concat(field.dbdefault.value);
              break;
            case 'string':
              value += "\"".concat(field.dbdefault.value, "\"");
              break;
            case 'expression':
              value += "`".concat(field.dbdefault.value, "`");
              break;
            default:
              break;
          }
          constraints.push(value);
        }
        if (field.note) {
          constraints.push("note: '".concat(DbmlExporter.escapeNote(field.note), "'"));
        }
        if (constraints.length > 0) {
          line += " [".concat(constraints.join(', '), "]");
        }
        return line;
      });
      return lines;
    }
  }, {
    key: "getIndexLines",
    value: function getIndexLines(tableId, model) {
      var table = model.tables[tableId];
      var lines = table.indexIds.map(function (indexId) {
        var line = '';
        var index = model.indexes[indexId];
        if (index.columnIds.length > 1) {
          line = "(".concat(index.columnIds.map(function (columnId) {
            var column = model.indexColumns[columnId];
            if (column.type === 'expression') {
              return "`".concat(column.value, "`");
            }
            return column.value;
          }).join(', '), ")");
        } else if (index.columnIds.length === 1) {
          var column = model.indexColumns[index.columnIds[0]];
          line = column.type === 'expression' ? "`".concat(column.value, "`") : column.value;
        }
        var indexSettings = [];
        if (index.pk) {
          indexSettings.push('pk');
        }
        if (index.type) {
          indexSettings.push("type: ".concat(index.type.toLowerCase()));
        }
        if (index.unique) {
          indexSettings.push('unique');
        }
        if (index.name) {
          indexSettings.push("name: \"".concat(index.name, "\""));
        }
        if (indexSettings.length > 1) {
          line += " [".concat(indexSettings.join(', '), "]");
        } else if (indexSettings.length === 1) {
          line += " [".concat(indexSettings[0], "]");
        }
        return line;
      });
      return lines;
    }
  }, {
    key: "getTableContentArr",
    value: function getTableContentArr(tableIds, model) {
      var tableContentArr = tableIds.map(function (tableId) {
        var fieldContents = DbmlExporter.getFieldLines(tableId, model);
        var indexContents = DbmlExporter.getIndexLines(tableId, model);
        return {
          tableId: tableId,
          fieldContents: fieldContents,
          indexContents: indexContents
        };
      });
      return tableContentArr;
    }
  }, {
    key: "getTableSettings",
    value: function getTableSettings(table) {
      var settingStr = '';
      var settingSep = ', ';
      if (table.headerColor) {
        settingStr += "headerColor: ".concat(table.headerColor).concat(settingSep);
      }
      if (settingStr.endsWith(', ')) {
        settingStr = settingStr.replace(/,\s$/, '');
      }
      return settingStr ? " [".concat(settingStr, "]") : '';
    }
  }, {
    key: "exportTables",
    value: function exportTables(tableIds, model) {
      var _this = this;
      var tableContentArr = DbmlExporter.getTableContentArr(tableIds, model);
      var tableStrs = tableContentArr.map(function (tableContent) {
        var table = model.tables[tableContent.tableId];
        var schema = model.schemas[table.schemaId];
        var tableSettingStr = _this.getTableSettings(table);
        var indexStr = '';
        if (!_lodash["default"].isEmpty(tableContent.indexContents)) {
          indexStr = "\nIndexes {\n".concat(tableContent.indexContents.map(function (indexLine) {
            return "  ".concat(indexLine);
          }).join('\n'), "\n}");
        }
        var tableNote = table.note ? "  Note: '".concat(DbmlExporter.escapeNote(table.note), "'\n") : '';
        var tableStr = "Table ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(table.name, "\"").concat(tableSettingStr, " {\n").concat(tableContent.fieldContents.map(function (line) {
          return "  ".concat(line);
        }).join('\n'), "\n").concat(indexStr ? "".concat(indexStr, "\n") : '').concat(tableNote, "}\n");
        return tableStr;
      });
      return tableStrs.length ? tableStrs.join('\n') : '';
    }
  }, {
    key: "buildFieldName",
    value: function buildFieldName(fieldIds, model) {
      var fieldNames = fieldIds.map(function (fieldId) {
        return "\"".concat(model.fields[fieldId].name, "\"");
      }).join(', ');
      return fieldIds.length === 1 ? fieldNames : "(".concat(fieldNames, ")");
    }
  }, {
    key: "exportRefs",
    value: function exportRefs(refIds, model) {
      var _this2 = this;
      var strArr = refIds.map(function (refId) {
        var ref = model.refs[refId];
        var refEndpointIndex = ref.endpointIds.findIndex(function (endpointId) {
          return model.endpoints[endpointId].relation === '1';
        });
        var foreignEndpointId = ref.endpointIds[1 - refEndpointIndex];
        var refEndpointId = ref.endpointIds[refEndpointIndex];
        var foreignEndpoint = model.endpoints[foreignEndpointId];
        var refEndpoint = model.endpoints[refEndpointId];
        var line = 'Ref';
        var refEndpointField = model.fields[refEndpoint.fieldIds[0]];
        var refEndpointTable = model.tables[refEndpointField.tableId];
        var refEndpointSchema = model.schemas[refEndpointTable.schemaId];
        var refEndpointFieldName = _this2.buildFieldName(refEndpoint.fieldIds, model, 'dbml');
        if (ref.name) {
          line += " ".concat((0, _utils.shouldPrintSchema)(model.schemas[ref.schemaId], model) ? "\"".concat(model.schemas[ref.schemaId].name, "\".") : '', "\"").concat(ref.name, "\"");
        }
        line += ':';
        line += "".concat((0, _utils.shouldPrintSchema)(refEndpointSchema, model) ? "\"".concat(refEndpointSchema.name, "\".") : '', "\"").concat(refEndpointTable.name, "\".").concat(refEndpointFieldName, " ");
        var foreignEndpointField = model.fields[foreignEndpoint.fieldIds[0]];
        var foreignEndpointTable = model.tables[foreignEndpointField.tableId];
        var foreignEndpointSchema = model.schemas[foreignEndpointTable.schemaId];
        var foreignEndpointFieldName = _this2.buildFieldName(foreignEndpoint.fieldIds, model, 'dbml');
        if (foreignEndpoint.relation === '1') line += '- ';else line += '< ';
        line += "".concat((0, _utils.shouldPrintSchema)(foreignEndpointSchema, model) ? "\"".concat(foreignEndpointSchema.name, "\".") : '', "\"").concat(foreignEndpointTable.name, "\".").concat(foreignEndpointFieldName);
        var refActions = [];
        if (ref.onUpdate) {
          refActions.push("update: ".concat(ref.onUpdate.toLowerCase()));
        }
        if (ref.onDelete) {
          refActions.push("delete: ".concat(ref.onDelete.toLowerCase()));
        }
        if (refActions.length > 0) {
          line += " [".concat(refActions.join(', '), "]");
        }
        line += '\n';
        return line;
      });
      return strArr.length ? strArr.join('\n') : '';
    }
  }, {
    key: "exportTableGroups",
    value: function exportTableGroups(tableGroupIds, model) {
      var tableGroupStrs = tableGroupIds.map(function (groupId) {
        var group = model.tableGroups[groupId];
        var groupSchema = model.schemas[group.schemaId];
        return "TableGroup ".concat((0, _utils.shouldPrintSchema)(groupSchema, model) ? "\"".concat(groupSchema.name, "\".") : '', "\"").concat(group.name, "\" {\n").concat(group.tableIds.map(function (tableId) {
          var table = model.tables[tableId];
          var tableSchema = model.schemas[table.schemaId];
          return "  ".concat((0, _utils.shouldPrintSchema)(tableSchema, model) ? "\"".concat(tableSchema.name, "\".") : '', "\"").concat(table.name, "\"");
        }).join('\n'), "\n}\n");
      });
      return tableGroupStrs.length ? tableGroupStrs.join('\n') : '';
    }
  }, {
    key: "export",
    value: function _export(model) {
      var res = '';
      var hasBlockAbove = false;
      var database = model.database['1'];
      database.schemaIds.forEach(function (schemaId) {
        var _model$schemas$schema = model.schemas[schemaId],
          enumIds = _model$schemas$schema.enumIds,
          tableIds = _model$schemas$schema.tableIds,
          tableGroupIds = _model$schemas$schema.tableGroupIds,
          refIds = _model$schemas$schema.refIds;
        if (!_lodash["default"].isEmpty(enumIds)) {
          if (hasBlockAbove) res += '\n';
          res += DbmlExporter.exportEnums(enumIds, model);
          hasBlockAbove = true;
        }
        if (!_lodash["default"].isEmpty(tableIds)) {
          if (hasBlockAbove) res += '\n';
          res += DbmlExporter.exportTables(tableIds, model);
          hasBlockAbove = true;
        }
        if (!_lodash["default"].isEmpty(tableGroupIds)) {
          if (hasBlockAbove) res += '\n';
          res += DbmlExporter.exportTableGroups(tableGroupIds, model);
          hasBlockAbove = true;
        }
        if (!_lodash["default"].isEmpty(refIds)) {
          if (hasBlockAbove) res += '\n';
          res += DbmlExporter.exportRefs(refIds, model);
          hasBlockAbove = true;
        }
      });
      return res;
    }
  }]);
  return DbmlExporter;
}();
var _default = DbmlExporter;
exports["default"] = _default;