"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var DriverUtils_1 = require("../DriverUtils");
var DriverOptionNotSetError_1 = require("../error/DriverOptionNotSetError");
var DateUtils_1 = require("../../util/DateUtils");
var WebsqlQueryRunner_1 = require("./WebsqlQueryRunner");
var RdbmsSchemaBuilder_1 = require("../../schema-builder/RdbmsSchemaBuilder");
/**
 * Organizes communication with WebSQL in the browser.
 */
var WebsqlDriver = (function () {
    // -------------------------------------------------------------------------
    // Constructor
    // -------------------------------------------------------------------------
    function WebsqlDriver(connection) {
        // -------------------------------------------------------------------------
        // Public Implemented Properties
        // -------------------------------------------------------------------------
        /**
         * Gets list of supported column data types by a driver.
         *
         * @see https://www.tutorialspoint.com/sqlite/sqlite_data_types.htm
         * @see https://sqlite.org/datatype3.html
         */
        this.supportedDataTypes = [
            "int",
            "integer",
            "tinyint",
            "smallint",
            "mediumint",
            "bigint",
            "int2",
            "int8",
            "integer",
            "character",
            "varchar",
            "varying character",
            "nchar",
            "native character",
            "nvarchar",
            "text",
            "clob",
            "text",
            "blob",
            "real",
            "double",
            "double precision",
            "float",
            "real",
            "numeric",
            "decimal",
            "boolean",
            "date",
            "datetime",
        ];
        /**
         * Orm has special columns and we need to know what database column types should be for those types.
         * Column types are driver dependant.
         */
        this.mappedDataTypes = {
            createDate: "datetime",
            createDateDefault: "datetime('now')",
            updateDate: "datetime",
            updateDateDefault: "datetime('now')",
            version: "int",
            treeLevel: "int",
            migrationName: "varchar",
            migrationTimestamp: "bigint",
        };
        this.connection = connection;
        this.options = connection.options;
        Object.assign(connection.options, DriverUtils_1.DriverUtils.buildDriverOptions(connection.options)); // todo: do it better way
        // validate options to make sure everything is set
        // if (!this.options.host)
        //     throw new DriverOptionNotSetError("host");
        // if (!this.options.username)
        //     throw new DriverOptionNotSetError("username");
        if (!this.options.database)
            throw new DriverOptionNotSetError_1.DriverOptionNotSetError("database");
        // todo: what about extra options: version, description, size
    }
    // -------------------------------------------------------------------------
    // Public Methods
    // -------------------------------------------------------------------------
    /**
     * Performs connection to the database.
     * Based on pooling options, it can either create connection immediately,
     * either create a pool and create connection when needed.
     */
    WebsqlDriver.prototype.connect = function () {
        return Promise.resolve();
    };
    /**
     * Closes connection with the database.
     */
    WebsqlDriver.prototype.disconnect = function () {
        return Promise.resolve();
        // if (!this.databaseConnection)
        //     throw new ConnectionIsNotSetError("websql");
        // return new Promise<void>((ok, fail) => {
        // const handler = (err: any) => err ? fail(err) : ok();
        // todo: find out how to close connection
        // ok();
        // });
    };
    /**
     * Creates a schema builder used to build and sync a schema.
     */
    WebsqlDriver.prototype.createSchemaBuilder = function () {
        return new RdbmsSchemaBuilder_1.RdbmsSchemaBuilder(this.connection);
    };
    /**
     * Creates a query runner used to execute database queries.
     */
    WebsqlDriver.prototype.createQueryRunner = function () {
        return new WebsqlQueryRunner_1.WebsqlQueryRunner(this);
    };
    /**
     * Replaces parameters in the given sql with special escaping character
     * and an array of parameter names to be passed to a query.
     */
    WebsqlDriver.prototype.escapeQueryWithParameters = function (sql, parameters) {
        if (!parameters || !Object.keys(parameters).length)
            return [sql, []];
        var escapedParameters = [];
        var keys = Object.keys(parameters).map(function (parameter) { return "(:" + parameter + "\\b)"; }).join("|");
        sql = sql.replace(new RegExp(keys, "g"), function (key) {
            escapedParameters.push(parameters[key.substr(1)]);
            return "?";
        }); // todo: make replace only in value statements, otherwise problems
        return [sql, escapedParameters];
    };
    /**
     * Escapes a column name.
     */
    WebsqlDriver.prototype.escapeColumn = function (columnName) {
        return columnName; // "`" + columnName + "`";
    };
    /**
     * Escapes an alias.
     */
    WebsqlDriver.prototype.escapeAlias = function (aliasName) {
        return aliasName; // "`" + aliasName + "`";
    };
    /**
     * Escapes a table name.
     */
    WebsqlDriver.prototype.escapeTable = function (tableName) {
        return tableName; // "`" + tableName + "`";
    };
    /**
     * Prepares given value to a value to be persisted, based on its column type and metadata.
     */
    WebsqlDriver.prototype.preparePersistentValue = function (value, columnMetadata) {
        if (value === null || value === undefined)
            return value;
        if (columnMetadata.type === Boolean) {
            return value === true ? 1 : 0;
        }
        else if (columnMetadata.type === "date") {
            return DateUtils_1.DateUtils.mixedDateToDateString(value);
        }
        else if (columnMetadata.type === "time") {
            return DateUtils_1.DateUtils.mixedDateToTimeString(value);
        }
        else if (columnMetadata.type === "datetime") {
            return DateUtils_1.DateUtils.mixedDateToUtcDatetimeString(value);
        }
        else if (columnMetadata.type === "json") {
            return JSON.stringify(value);
        }
        else if (columnMetadata.type === "simple-array") {
            return DateUtils_1.DateUtils.simpleArrayToString(value);
        }
        return value;
    };
    /**
     * Prepares given value to a value to be persisted, based on its column type or metadata.
     */
    WebsqlDriver.prototype.prepareHydratedValue = function (value, columnMetadata) {
        if (columnMetadata.type === Boolean) {
            return value ? true : false;
        }
        else if (columnMetadata.type === "datetime") {
            return DateUtils_1.DateUtils.normalizeHydratedDate(value);
        }
        else if (columnMetadata.type === "date") {
            return DateUtils_1.DateUtils.mixedDateToDateString(value);
        }
        else if (columnMetadata.type === "time") {
            return DateUtils_1.DateUtils.mixedTimeToString(value);
        }
        else if (columnMetadata.type === "json") {
            return JSON.parse(value);
        }
        else if (columnMetadata.type === "simple-array") {
            return DateUtils_1.DateUtils.stringToSimpleArray(value);
        }
        return value;
    };
    /**
     * Creates a database type from a given column metadata.
     */
    WebsqlDriver.prototype.normalizeType = function (column) {
        var type = "";
        if (column.type === Number) {
            type += "integer";
        }
        else if (column.type === String) {
            type += "varchar";
        }
        else if (column.type === Date) {
            type += "datetime";
        }
        else if (column.type === Boolean) {
            type += "boolean";
        }
        else if (column.type === Object) {
            type += "text";
        }
        else if (column.type === "simple-array") {
            type += "text";
        }
        else {
            type += column.type;
        }
        if (column.length) {
            type += "(" + column.length + ")";
        }
        else if (column.precision && column.scale) {
            type += "(" + column.precision + "," + column.scale + ")";
        }
        else if (column.precision) {
            type += "(" + column.precision + ")";
        }
        else if (column.scale) {
            type += "(" + column.scale + ")";
        }
        return type;
    };
    /**
     * Normalizes "default" value of the column.
     */
    WebsqlDriver.prototype.normalizeDefault = function (column) {
        if (typeof column.default === "number") {
            return "" + column.default;
        }
        else if (typeof column.default === "boolean") {
            return column.default === true ? "1" : "0";
        }
        else if (typeof column.default === "function") {
            return column.default();
        }
        else if (typeof column.default === "string") {
            return "'" + column.default + "'";
        }
        else {
            return column.default;
        }
    };
    return WebsqlDriver;
}());
exports.WebsqlDriver = WebsqlDriver;

//# sourceMappingURL=WebsqlDriver.js.map
