/**
 * @file recordsService.js
 * @author Radim Buráň (xburan03@stud.fit.vutbr.cz)
 */

const db = require('./dbService');
const {Point} = require("@influxdata/influxdb-client");
require('dotenv').config();


async function write(data) {
    if (!data.hasOwnProperty('measurement') || data.measurement === undefined || data.measurement === null) {
        return {error: "No measurement specified!"};
    }
    if (!data.hasOwnProperty('device') || data.device === undefined || data.device === null) {
        return {error: "No device specified!"};
    }

    const p = new Point(data.measurement)
        .tag('device', data.device);

    if (data.hasOwnProperty('float') && data.float !== undefined && data.float !== null) {
        p.floatField('value', data.float);
    }

    if (data.hasOwnProperty('string') && data.string !== undefined && data.string !== null) {
        p.stringField('svalue', data.string);
    }

    const wapi = db.influxWriteAPI();

    wapi.writePoint(p);

    wapi.flush().then((r) => {
            return r;
        }).catch((e) => {
            return {error: e}
        });
}

async function read(data) {
    let fluxQuery = 'from(bucket:"' + process.env.INFLUX_BUCKET + '")';

    const range = data.range || "-30d";
    fluxQuery += ` |> range(start: ${range})`;

    if (!data.hasOwnProperty("device") || data.device === undefined) {
        return {error: "No device specified!"};
    }

    if (!data.hasOwnProperty("measurement") || data.measurement === undefined) {
        return {error: "No measurement specified!"};
    }

    fluxQuery += ` |> filter(fn: (r) => r._measurement == "${data.measurement}")`;
    fluxQuery += ` |> filter(fn: (r) => r.device == "${data.device}")`;

    const result = await db.influxQueryAPI().collectRows(fluxQuery);

    const res = {
        legend: result.map((row) => row._time),
        data: result.map((row) => row._value)
    };

    return res;
}

/**
 * Used to get last data for specific device
 * @param data (device, measurement[opt])
 * @returns {Promise<Array<unknown>|{error: string}>}
 */
async function readLast(data) {
    let fluxQuery = 'from(bucket:"' + process.env.INFLUX_BUCKET + '") |> range(start: -30d)';

    if (!data.hasOwnProperty("device") || data.device === undefined) {
        return {error: "No device specified!"};
    }

    if (!data.hasOwnProperty("measurement") && data.measurement !== undefined && data.measurement !== null) {
        fluxQuery += ` |> filter(fn: (r) => r._measurement == "${data.measurement}")`;
    }

    fluxQuery += ` |> filter(fn: (r) => r.device == "${data.device}")`;
    fluxQuery += " |> last()";

    const result = await db.influxQueryAPI().collectRows(fluxQuery);

    const res = {};

    result.forEach(line => res[line._measurement] = line._value);

    res["last_update"] = new Date(Math.max(...result.map(i => new Date(i._time))));

    return res;
}

module.exports = {
    write,
    read,
    readLast
}