"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ColumnSchema_1 = require("./ColumnSchema");
/**
 * Table schema in the database represented in this class.
 */
var TableSchema = (function () {
    // -------------------------------------------------------------------------
    // Constructor
    // -------------------------------------------------------------------------
    function TableSchema(name, columns, justCreated) {
        /**
         * Table columns.
         */
        this.columns = [];
        /**
         * Table indices.
         */
        this.indices = [];
        /**
         * Table foreign keys.
         */
        this.foreignKeys = [];
        /**
         * Table primary keys.
         */
        this.primaryKeys = [];
        /**
         * Indicates if table schema was just created.
         * This is needed, for example to check if we need to skip primary keys creation
         * for new table schemas.
         */
        this.justCreated = false;
        this.name = name;
        if (columns) {
            this.columns = columns.map(function (column) {
                if (column instanceof ColumnSchema_1.ColumnSchema) {
                    return column;
                }
                else {
                    return new ColumnSchema_1.ColumnSchema(column);
                }
            });
        }
        if (justCreated !== undefined)
            this.justCreated = justCreated;
    }
    Object.defineProperty(TableSchema.prototype, "primaryKeysWithoutGenerated", {
        // -------------------------------------------------------------------------
        // Accessors
        // -------------------------------------------------------------------------
        /**
         * Gets only those primary keys that does not
         */
        get: function () {
            var generatedColumn = this.columns.find(function (column) { return column.isGenerated; });
            if (!generatedColumn)
                return this.primaryKeys;
            return this.primaryKeys.filter(function (primaryKey) {
                return primaryKey.columnName !== generatedColumn.name;
            });
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(TableSchema.prototype, "hasGeneratedColumn", {
        get: function () {
            return !!this.columns.find(function (column) { return column.isGenerated; });
        },
        enumerable: true,
        configurable: true
    });
    // -------------------------------------------------------------------------
    // Public Methods
    // -------------------------------------------------------------------------
    /**
     * Clones this table schema to a new table schema with all properties cloned.
     */
    TableSchema.prototype.clone = function () {
        var cloned = new TableSchema(this.name);
        cloned.columns = this.columns.map(function (column) { return column.clone(); });
        cloned.indices = this.indices.map(function (index) { return index.clone(); });
        cloned.foreignKeys = this.foreignKeys.map(function (key) { return key.clone(); });
        cloned.primaryKeys = this.primaryKeys.map(function (key) { return key.clone(); });
        cloned.engine = this.engine;
        return cloned;
    };
    /**
     * Adds column schemas.
     */
    TableSchema.prototype.addColumns = function (columns) {
        this.columns = this.columns.concat(columns);
    };
    /**
     * Replaces given column.
     */
    TableSchema.prototype.replaceColumn = function (oldColumn, newColumn) {
        this.columns[this.columns.indexOf(oldColumn)] = newColumn;
    };
    /**
     * Removes a column schema from this table schema.
     */
    TableSchema.prototype.removeColumn = function (columnToRemove) {
        var foundColumn = this.columns.find(function (column) { return column.name === columnToRemove.name; });
        if (foundColumn)
            this.columns.splice(this.columns.indexOf(foundColumn), 1);
    };
    /**
     * Remove all column schemas from this table schema.
     */
    TableSchema.prototype.removeColumns = function (columns) {
        var _this = this;
        columns.forEach(function (column) { return _this.removeColumn(column); });
    };
    /**
     * Adds all given primary keys.
     */
    TableSchema.prototype.addPrimaryKeys = function (addedKeys) {
        var _this = this;
        addedKeys.forEach(function (key) { return _this.primaryKeys.push(key); });
    };
    /**
     * Removes all given primary keys.
     */
    TableSchema.prototype.removePrimaryKeys = function (droppedKeys) {
        var _this = this;
        droppedKeys.forEach(function (key) {
            _this.primaryKeys.splice(_this.primaryKeys.indexOf(key), 1);
        });
    };
    /**
     * Removes primary keys of the given columns.
     */
    TableSchema.prototype.removePrimaryKeysOfColumns = function (columns) {
        this.primaryKeys = this.primaryKeys.filter(function (primaryKey) {
            return !columns.find(function (column) { return column.name === primaryKey.columnName; });
        });
    };
    /**
     * Adds foreign key schemas.
     */
    TableSchema.prototype.addForeignKeys = function (foreignKeys) {
        this.foreignKeys = this.foreignKeys.concat(foreignKeys);
    };
    /**
     * Removes foreign key from this table schema.
     */
    TableSchema.prototype.removeForeignKey = function (removedForeignKey) {
        var fk = this.foreignKeys.find(function (foreignKey) { return foreignKey.name === removedForeignKey.name; }); // this must be by name
        if (fk)
            this.foreignKeys.splice(this.foreignKeys.indexOf(fk), 1);
    };
    /**
     * Removes all foreign keys from this table schema.
     */
    TableSchema.prototype.removeForeignKeys = function (dbForeignKeys) {
        var _this = this;
        dbForeignKeys.forEach(function (foreignKey) { return _this.removeForeignKey(foreignKey); });
    };
    /**
     * Removes index schema from this table schema.
     */
    TableSchema.prototype.removeIndex = function (indexSchema) {
        var index = this.indices.find(function (index) { return index.name === indexSchema.name; });
        if (index)
            this.indices.splice(this.indices.indexOf(index), 1);
    };
    /**
     * Differentiate columns of this table schema and columns from the given column metadatas columns
     * and returns only changed.
     */
    TableSchema.prototype.findChangedColumns = function (driver, columnMetadatas) {
        var _this = this;
        return this.columns.filter(function (columnSchema) {
            var columnMetadata = columnMetadatas.find(function (columnMetadata) { return columnMetadata.databaseName === columnSchema.name; });
            if (!columnMetadata)
                return false; // we don't need new columns, we only need exist and changed
            // console.log(columnSchema.name, "!==", columnMetadata.databaseName); //  ||
            // console.log(columnSchema.type, "!==", driver.normalizeType(columnMetadata)); // ||
            // console.log(columnSchema.comment, "!==", columnMetadata.comment); //  ||
            // console.log(this.compareDefaultValues(driver.normalizeDefault(columnMetadata), columnSchema.default)); // || // we included check for generated here, because generated columns already can have default values
            // console.log(columnSchema.isNullable, "!==", columnMetadata.isNullable); //  ||
            // console.log(columnSchema.isUnique, "!==", columnMetadata.isUnique); //  ||
            // console.log(columnSchema.isGenerated, "!==", columnMetadata.isGenerated); // d;
            return columnSchema.name !== columnMetadata.databaseName ||
                columnSchema.type !== driver.normalizeType(columnMetadata) ||
                columnSchema.comment !== columnMetadata.comment ||
                (!columnSchema.isGenerated && !_this.compareDefaultValues(driver.normalizeDefault(columnMetadata), columnSchema.default)) ||
                columnSchema.isNullable !== columnMetadata.isNullable ||
                columnSchema.isUnique !== columnMetadata.isUnique ||
                // columnSchema.isPrimary !== columnMetadata.isPrimary ||
                columnSchema.isGenerated !== columnMetadata.isGenerated;
        });
    };
    // -------------------------------------------------------------------------
    // Protected Methods
    // -------------------------------------------------------------------------
    /**
     * Checks if "DEFAULT" values in the column metadata and in the database schema are equal.
     */
    TableSchema.prototype.compareDefaultValues = function (columnMetadataValue, databaseValue) {
        // if (typeof columnMetadataValue === "number")
        //     return columnMetadataValue === parseInt(databaseValue);
        // if (typeof columnMetadataValue === "boolean")
        //     return columnMetadataValue === (!!databaseValue || databaseValue === "false");
        // if (typeof columnMetadataValue === "function")
        // if (typeof columnMetadataValue === "string" && typeof databaseValue === "string")
        //     return columnMetadataValue.toLowerCase() === databaseValue.toLowerCase();
        if (typeof columnMetadataValue === "string" && typeof databaseValue === "string") {
            // we need to cut out "((x))" where x number generated by mssql
            columnMetadataValue = columnMetadataValue.replace(/\(\([0-9.]*\)\)$/g, "$1");
            databaseValue = databaseValue.replace(/\(\(([0-9.]*?)\)\)$/g, "$1");
            // we need to cut out "(" because in mssql we can understand returned value is a string or a function
            // as result compare cannot understand if default is really changed or not
            columnMetadataValue = columnMetadataValue.replace(/^\(|\)$/g, "");
            databaseValue = databaseValue.replace(/^\(|\)$/g, "");
            // we need to cut out "'" because in mysql we can understand returned value is a string or a function
            // as result compare cannot understand if default is really changed or not
            columnMetadataValue = columnMetadataValue.replace(/^'+|'+$/g, "");
            databaseValue = databaseValue.replace(/^'+|'+$/g, "");
        }
        // console.log("columnMetadataValue", columnMetadataValue);
        // console.log("databaseValue", databaseValue);
        return columnMetadataValue === databaseValue;
    };
    // -------------------------------------------------------------------------
    // Static Methods
    // -------------------------------------------------------------------------
    /**
     * Creates table schema from a given entity metadata.
     *
     * todo: need deeper implementation
     */
    TableSchema.create = function (entityMetadata, driver) {
        var tableSchema = new TableSchema(entityMetadata.tableName);
        tableSchema.engine = entityMetadata.engine;
        entityMetadata.columns.forEach(function (column) {
            tableSchema.columns.push(ColumnSchema_1.ColumnSchema.create(column, driver.normalizeType(column), driver.normalizeDefault(column)));
        });
        return tableSchema;
    };
    return TableSchema;
}());
exports.TableSchema = TableSchema;

//# sourceMappingURL=TableSchema.js.map
