/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import _ from 'lodash';
import moment from 'moment';

/**
 * @typedef {{x: number, y: {[key: string]: number}}} IgniteChartDataPoint
 */

const RANGE_RATE_PRESET = [
    {label: '1 min', value: 1},
    {label: '5 min', value: 5},
    {label: '10 min', value: 10},
    {label: '15 min', value: 15},
    {label: '30 min', value: 30}
];

/**
 * Determines what label format was chosen by determineLabelFormat function
 * in Chart.js streaming plugin.
 * 
 * @param {string} label
 */
const inferLabelFormat = (label) => {
    if (label.match(/\.\d{3} (am|pm)$/)) return 'MMM D, YYYY h:mm:ss.SSS a';
    if (label.match(/:\d{1,2} (am|pm)$/)) return 'MMM D, YYYY h:mm:ss a';
    if (label.match(/ \d{4}$/)) return 'MMM D, YYYY';
};

export class IgniteChartController {
    /** @type {import('chart.js').ChartConfiguration} */
    chartOptions;
    /** @type {string} */
    chartTitle;
    /** @type {IgniteChartDataPoint} */
    chartDataPoint;
    /** @type {Array<IgniteChartDataPoint>} */
    chartHistory;
    newPoints = [];

    static $inject = ['$element', 'IgniteChartColors', '$filter'];

    /**
     * @param {JQLite} $element
     * @param {Array<string>} IgniteChartColors
     * @param {ng.IFilterService} $filter
     */
    constructor($element, IgniteChartColors, $filter) {
        this.$element = $element;
        this.IgniteChartColors = IgniteChartColors;

        this.datePipe = $filter('date');
        this.ranges = RANGE_RATE_PRESET;
        this.currentRange = this.ranges[0];
        this.maxRangeInMilliseconds = RANGE_RATE_PRESET[RANGE_RATE_PRESET.length - 1].value * 60 * 1000;
        this.ctx = this.$element.find('canvas')[0].getContext('2d');

        this.localHistory = [];
        this.updateIsBusy = false;
    }

    $onDestroy() {
        if (this.chart)
            this.chart.destroy();

        this.$element = this.ctx = this.chart = null;
    }

    $onInit() {
        this.chartColors = _.get(this.chartOptions, 'chartColors', this.IgniteChartColors);
    }

    _refresh() {
        this.onRefresh();
        this.rerenderChart();
    }

    /**
     * @param {{chartOptions: ng.IChangesObject<import('chart.js').ChartConfiguration>, chartTitle: ng.IChangesObject<string>, chartDataPoint: ng.IChangesObject<IgniteChartDataPoint>, chartHistory: ng.IChangesObject<Array<IgniteChartDataPoint>>}} changes
     */
    async $onChanges(changes) {
        if (this.chart && _.get(changes, 'refreshRate.currentValue'))
            this.onRefreshRateChanged(_.get(changes, 'refreshRate.currentValue'));

        if ((changes.chartDataPoint && _.isNil(changes.chartDataPoint.currentValue)) ||
            (changes.chartHistory && _.isEmpty(changes.chartHistory.currentValue))) {
            this.clearDatasets();
            this.localHistory = [];

            return;
        }

        if (changes.chartHistory && changes.chartHistory.currentValue && changes.chartHistory.currentValue.length !== changes.chartHistory.previousValue.length) {
            if (!this.chart)
                await this.initChart();

            this.clearDatasets();
            this.localHistory = [...changes.chartHistory.currentValue];

            this.newPoints.splice(0, this.newPoints.length, ...changes.chartHistory.currentValue);

            this._refresh();

            return;
        }

        if (this.chartDataPoint && changes.chartDataPoint) {
            if (!this.chart)
                this.initChart();

            this.newPoints.push(this.chartDataPoint);
            this.localHistory.push(this.chartDataPoint);

            this._refresh();
        }
    }

    async initChart() {
        /** @type {import('chart.js').ChartConfiguration} */
        this.config = {
            type: 'LineWithVerticalCursor',
            data: {
                datasets: []
            },
            options: {
                elements: {
                    line: {
                        tension: 0
                    },
                    point: {
                        radius: 2,
                        pointStyle: 'rectRounded'
                    }
                },
                animation: {
                    duration: 0 // general animation time
                },
                hover: {
                    animationDuration: 0 // duration of animations when hovering an item
                },
                responsiveAnimationDuration: 0, // animation duration after a resize
                maintainAspectRatio: false,
                responsive: true,
                legend: {
                    display: false
                },
                scales: {
                    xAxes: [{
                        type: 'realtime',
                        display: true,
                        time: {
                            displayFormats: {
                                second: 'HH:mm:ss',
                                minute: 'HH:mm:ss',
                                hour: 'HH:mm:ss'
                            }
                        },
                        ticks: {
                            maxRotation: 0,
                            minRotation: 0
                        }
                    }],
                    yAxes: [{
                        type: 'linear',
                        display: true,
                        ticks: {
                            min: 0,
                            beginAtZero: true,
                            maxTicksLimit: 4,
                            callback: (value, index, labels) => {
                                if (value === 0)
                                    return 0;

                                if (_.max(labels) <= 4000 && value <= 4000)
                                    return value;

                                if (_.max(labels) <= 1000000 && value <= 1000000)
                                    return `${value / 1000}K`;

                                if ((_.max(labels) <= 4000000 && value >= 500000) || (_.max(labels) > 4000000))
                                    return `${value / 1000000}M`;

                                return value;
                            }
                        }
                    }]
                },
                tooltips: {
                    mode: 'index',
                    position: 'yCenter',
                    intersect: false,
                    yAlign: 'center',
                    xPadding: 20,
                    yPadding: 20,
                    bodyFontSize: 13,
                    callbacks: {
                        title: (tooltipItem) => {
                            return tooltipItem[0].xLabel = moment(tooltipItem[0].xLabel, inferLabelFormat(tooltipItem[0].xLabel)).format('HH:mm:ss');
                        },
                        label: (tooltipItem, data) => {
                            const label = data.datasets[tooltipItem.datasetIndex].label || '';

                            return `${_.startCase(label)}: ${tooltipItem.yLabel} per sec`;
                        },
                        labelColor: (tooltipItem) => {
                            return {
                                borderColor: 'rgba(255,255,255,0.5)',
                                borderWidth: 0,
                                boxShadow: 'none',
                                backgroundColor: this.chartColors[tooltipItem.datasetIndex]
                            };
                        }
                    }
                },
                plugins: {
                    streaming: {
                        duration: this.currentRange.value * 1000 * 60,
                        frameRate: 1000 / this.refreshRate || 1 / 3,
                        refresh: this.refreshRate || 3000,
                        // Temporary workaround before https://github.com/nagix/chartjs-plugin-streaming/issues/53 resolved.
                        // ttl: this.maxRangeInMilliseconds,
                        onRefresh: () => {
                            this.onRefresh();
                        }
                    }
                }
            }
        };

        this.config = _.merge(this.config, this.chartOptions);

        const chartModule = await import('chart.js');
        const Chart = chartModule.default;

        Chart.Tooltip.positioners.yCenter = (elements) => {
            const chartHeight = elements[0]._chart.height;
            const tooltipHeight = 60;

            return {x: elements[0].getCenterPoint().x, y: Math.floor(chartHeight / 2) - Math.floor(tooltipHeight / 2) };
        };


        // Drawing vertical cursor
        Chart.defaults.LineWithVerticalCursor = Chart.defaults.line;
        Chart.controllers.LineWithVerticalCursor = Chart.controllers.line.extend({
            draw(ease) {
                Chart.controllers.line.prototype.draw.call(this, ease);

                if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
                    const activePoint = this.chart.tooltip._active[0];
                    const ctx = this.chart.ctx;
                    const x = activePoint.tooltipPosition().x;
                    const topY = this.chart.scales['y-axis-0'].top;
                    const bottomY = this.chart.scales['y-axis-0'].bottom;

                    // draw line
                    ctx.save();
                    ctx.beginPath();
                    ctx.moveTo(x, topY);
                    ctx.lineTo(x, bottomY);
                    ctx.lineWidth = 0.5;
                    ctx.strokeStyle = '#0080ff';
                    ctx.stroke();
                    ctx.restore();
                }
            }
        });

        await import('chartjs-plugin-streaming');

        this.chart = new Chart(this.ctx, this.config);
        this.changeXRange(this.currentRange);
    }

    onRefresh() {
        this.newPoints.forEach((point) => {
            this.appendChartPoint(point);
        });

        this.newPoints.splice(0, this.newPoints.length);
    }

    /**
     * @param {IgniteChartDataPoint} dataPoint
     */
    appendChartPoint(dataPoint) {
        Object.keys(dataPoint.y).forEach((key) => {
            if (this.checkDatasetCanBeAdded(key)) {
                let datasetIndex = this.findDatasetIndex(key);

                if (datasetIndex < 0) {
                    datasetIndex = this.config.data.datasets.length;
                    this.addDataset(key);
                }

                this.config.data.datasets[datasetIndex].data.push({x: dataPoint.x, y: dataPoint.y[key]});
                this.config.data.datasets[datasetIndex].borderColor = this.chartColors[datasetIndex];
                this.config.data.datasets[datasetIndex].borderWidth = 2;
                this.config.data.datasets[datasetIndex].fill = false;
            }
        });

        // Temporary workaround before https://github.com/nagix/chartjs-plugin-streaming/issues/53 resolved.
        this.pruneHistory();
    }

    // Temporary workaround before https://github.com/nagix/chartjs-plugin-streaming/issues/53 resolved.
    pruneHistory() {
        if (!this.xRangeUpdateInProgress) {
            const currenTime = Date.now();

            while (currenTime - this.localHistory[0].x > this.maxRangeInMilliseconds)
                this.localHistory.shift();

            this.config.data.datasets.forEach((dataset) => {
                while (currenTime - dataset.data[0].x > this.maxRangeInMilliseconds)
                    dataset.data.shift();
            });
        }
    }

    /**
     * Checks if a key of dataset can be added to chart or should be ignored.
     * @param dataPointKey {String}
     * @return {Boolean}
     */
    checkDatasetCanBeAdded(dataPointKey) {
        // If datasetLegendMapping is empty all keys are allowed.
        if (!this.config.datasetLegendMapping)
            return true;

        return Object.keys(this.config.datasetLegendMapping).includes(dataPointKey);
    }

    clearDatasets() {
        if (!_.isNil(this.config))
            this.config.data.datasets.forEach((dataset) => dataset.data = []);
    }

    addDataset(datasetName) {
        if (this.findDatasetIndex(datasetName) >= 0)
            throw new Error(`Dataset with name ${datasetName} is already in chart`);
        else {
            const datasetIsHidden = _.isNil(this.config.datasetLegendMapping[datasetName].hidden)
                ? false
                : this.config.datasetLegendMapping[datasetName].hidden;

            this.config.data.datasets.push({ label: datasetName, data: [], hidden: datasetIsHidden });
        }
    }

    findDatasetIndex(searchedDatasetLabel) {
        return this.config.data.datasets.findIndex((dataset) => dataset.label === searchedDatasetLabel);
    }

    changeXRange(range) {
        if (this.chart) {
            this.xRangeUpdateInProgress = true;

            this.chart.config.options.plugins.streaming.duration = range.value * 60 * 1000;

            this.clearDatasets();
            this.newPoints.splice(0, this.newPoints.length, ...this.localHistory);

            this.onRefresh();
            this.rerenderChart();

            this.xRangeUpdateInProgress = false;
        }
    }

    onRefreshRateChanged(refreshRate) {
        this.chart.config.options.plugins.streaming.frameRate = 1000 / refreshRate;
        this.chart.config.options.plugins.streaming.refresh = refreshRate;
        this.rerenderChart();
    }

    rerenderChart() {
        if (this.chart)
            this.chart.update();
    }
}
