"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HotDBInflux = void 0;
const influxdb_client_1 = require("@influxdata/influxdb-client");
const HotDB_1 = require("../HotDB");
/**
 * The Influx database connection.
 */
class HotDBInflux extends HotDB_1.HotDB {
    constructor(db = null, type = HotDB_1.HotDBType.Influx, schema = null) {
        super(db, type, schema);
    }
    /**
     * Connect to the database.
     */
    connect(connectionInfo) {
        return __awaiter(this, void 0, void 0, function* () {
            return (new Promise((resolve, reject) => {
                let influxConnection = {
                    "url": connectionInfo.server
                };
                if (connectionInfo.org == null)
                    throw new Error(`An org must be specified when connecting to Influx.`);
                if (connectionInfo.database == null)
                    throw new Error(`A database (aka bucket) must be specified when connecting to Influx.`);
                if (connectionInfo.ssl != null)
                    throw new Error(`SSL is not supported for Influx at this time.`);
                if (connectionInfo.token != null)
                    influxConnection.token = connectionInfo.token;
                else {
                    // This is mostly for Influx 1.8
                    influxConnection.token = `${connectionInfo.username}:${connectionInfo.password}`;
                }
                try {
                    if (connectionInfo.connectionObjectOverride != null)
                        influxConnection = connectionInfo.connectionObjectOverride;
                    this.connectionStatus = HotDB_1.ConnectionStatus.Connecting;
                    this.db = new influxdb_client_1.InfluxDB(influxConnection);
                    this.writeApi = this.db.getWriteApi(connectionInfo.org, connectionInfo.database);
                    this.queryApi = this.db.getQueryApi(connectionInfo.org);
                    this.connectionStatus = HotDB_1.ConnectionStatus.Connected;
                    resolve([true]);
                }
                catch (ex) {
                    throw new Error(ex.message);
                }
            }));
        });
    }
    /**
     * Checks to see if this has a database connection.
     */
    dbCheck() {
        if (this.db == null)
            throw new Error("Not connected to a database!");
    }
    /**
     * Write to the database. This will only store the point. It will not send to the database
     * unless sendPoints is called.
     */
    addPoint(point) {
        if (this.queryApi == null)
            throw new Error("The Influx query API is not instantiated! Is Influx connected?");
        this.writeApi.writePoint(point);
    }
    /**
     * Write to the database. This will only store the points. It will not send to the database
     * unless sendPoints is called.
     */
    addPoints(points) {
        if (this.queryApi == null)
            throw new Error("The Influx query API is not instantiated! Is Influx connected?");
        this.writeApi.writePoints(points);
    }
    /**
     * Writes all stored points to the database.
     */
    sendPoints() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.queryApi == null)
                throw new Error("The Influx query API is not instantiated! Is Influx connected?");
            return (new Promise((resolve, reject) => {
                this.writeApi.close().then(() => {
                    resolve();
                })
                    .catch((ex) => {
                    throw new Error(ex.message);
                });
            }));
        });
    }
    /**
     * Write to the database. This will call close and send the point immediately to the database.
     * Do not use this to send lots of data. If you're sending batches of data, be sure to use
     * writePoints.
     */
    write(point) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.queryApi == null)
                throw new Error("The Influx query API is not instantiated! Is Influx connected?");
            this.addPoint(point);
            return (this.sendPoints());
        });
    }
    /**
     * Write points to the database. This will call close and send the point immediately to the database.
     */
    writePoints(points) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.queryApi == null)
                throw new Error("The Influx query API is not instantiated! Is Influx connected?");
            this.addPoints(points);
            return (this.sendPoints());
        });
    }
    /**
     * The query to make.
     */
    query(queryString_1) {
        return __awaiter(this, arguments, void 0, function* (queryString, values = [], nextFunc = null, errorFunc = null) {
            if (this.queryApi == null)
                throw new Error("The Influx query API is not instantiated! Is Influx connected?");
            return (new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
                let ary = [{ raw: [queryString] }];
                for (let iIdx = 0; iIdx < values.length; iIdx++) {
                    let value = values[iIdx];
                    ary.push(value);
                }
                /// @fixme Is this correct? wtf? Hardly any documentation on TemplateStringsArray or flux usage.
                let inputQuery = String.raw.apply(String, ary);
                this.queryApi.queryRows(inputQuery, {
                    "next": (row, tableMeta) => {
                        if (nextFunc != null)
                            nextFunc(row, tableMeta);
                    },
                    "error": (errorObj) => {
                        if (errorFunc != null)
                            errorFunc(errorObj);
                    },
                    "complete": () => {
                        resolve();
                    }
                });
            })));
        });
    }
    /**
     * Disconnect from the server.
     */
    disconnect() {
        return __awaiter(this, void 0, void 0, function* () {
            this.dbCheck();
            this.queryApi = null;
            yield this.writeApi.close();
            this.db = null;
        });
    }
}
exports.HotDBInflux = HotDBInflux;
//# sourceMappingURL=HotDBInflux.js.map