import * as tslib_1 from "tslib";
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone } from '@angular/core';
import { generateColorsBySeries, generateColorsByDataPoints } from './color.helpers';
import { DecimalPipe } from '@angular/common';
import { Chart } from 'chart.js';
import * as _ from 'lodash';
import * as moment from 'moment';
import { BaseChart, formatMoney, formatScale } from './base.chart';
/**
 * @internal
 */
var MULTI_SERIES_BY_DEFAULT = ['line', 'bar', 'horizontalBar', 'radar'];
/**
 * @internal
 */
export function getTooltipLabelCallBack(currency, percentage, digitInfo) {
    return function (tooltipItem, data) {
        var labels = [];
        var ds = data.datasets;
        var label = ds.length > 1 ? ds[tooltipItem.datasetIndex || 0].label || '' : '';
        if (label) {
            labels.push(label);
        }
        var dsData = ds[tooltipItem.datasetIndex || 0].data || [];
        var point = dsData[tooltipItem.index || 0];
        var value = _.isNumber(point) ? point : point.y;
        if (percentage !== 'only') {
            if (currency) {
                labels.push(formatMoney(value, currency, digitInfo));
            }
            else if (digitInfo && _.isNumber(value)) {
                labels.push(new DecimalPipe(moment.locale()).transform(value, digitInfo));
            }
            else {
                labels.push(tooltipItem.yLabel || value);
            }
        }
        if (percentage) {
            var total = _.sumBy(dsData, function (d) { return (_.isNumber(d) ? d : d.y); });
            labels.push((value && total ? (value * 100 / total).toFixed(2) : 0) + "%");
        }
        return labels;
    };
}
function splitWords(text, maxLength) {
    var words = [];
    var word = '';
    text.split(' ').forEach(function (w) {
        word = _.join([word, w], ' ');
        if (word.length > maxLength) {
            words.push(word);
            word = '';
        }
    });
    if (word) {
        words.push(word);
    }
    return words;
}
/**
 * @internal
 */
export function getTooltipTitleCallBack(horizontal) {
    return function (tooltipItems, data) {
        // Pick first xLabel for now
        var title = '';
        var labels = data.labels || [];
        var labelCount = labels.length;
        if (tooltipItems.length > 0) {
            var item = tooltipItems[0];
            if (item.xLabel || (horizontal && item.yLabel)) {
                title = (horizontal ? item.yLabel : item.xLabel) || '';
            }
            else if ((labelCount > 0 && item.index) || 0 < labelCount) {
                title = labels[item.index || 0];
            }
        }
        return splitWords(title, 15);
    };
}
var ChartComponent = /** @class */ (function (_super) {
    tslib_1.__extends(ChartComponent, _super);
    function ChartComponent(zone) {
        var _this = _super.call(this, zone) || this;
        _this._config = {};
        _this._prevConfig = {};
        return _this;
    }
    ChartComponent.prototype._onDestroy = function () {
        if (this._chart) {
            this._chart.destroy();
        }
    };
    ChartComponent.prototype._checkUpdate = function (resized) {
        var dataOrParamsChanged = false;
        if (this.paramsChanged) {
            this._applyConfig();
            dataOrParamsChanged = true;
        }
        dataOrParamsChanged = dataOrParamsChanged || !_.isEqual(this._config.data, this._prevConfig.data);
        var configChanged = !_.isEqual(JSON.stringify(this._config.options), JSON.stringify(this._prevConfig.options)) ||
            this._config.type !== this._prevConfig.type;
        configChanged = configChanged || this.isParamChanged('colorsFor');
        configChanged = configChanged || this.isParamChanged('colors');
        configChanged = configChanged || this.isParamChanged('percentage');
        configChanged = configChanged || this.isParamChanged('currency');
        configChanged = configChanged || this.isParamChanged('timeFormat');
        if (dataOrParamsChanged || configChanged) {
            this._refresh(configChanged);
        }
    };
    ChartComponent.prototype._refresh = function (configChanged) {
        this._prevConfig = _.cloneDeep(this._config);
        this.resetParamsChangeState();
        if (configChanged || !this._chart) {
            if (this._chart) {
                this._chart.destroy();
            }
            var cfg = _.cloneDeep(this._prevConfig);
            this._applyColors(this.colors || [], this.colorsFor || 'auto', (cfg.data || {}).datasets || []);
            this._createNewChart(cfg);
        }
        else {
            this._chart.config.data = _.cloneDeep(this._config.data || {});
            this._applyColors(this.colors || [], this.colorsFor || 'auto', this._chart.config.data.datasets || []);
            this._chart.update();
        }
    };
    ChartComponent.prototype._createNewChart = function (cfg) {
        var _this = this;
        this._zone.runOutsideAngular(function () {
            var container = _this._chartContainer.nativeElement;
            var nodes = container.getElementsByTagName('canvas');
            if (nodes.length) {
                container.removeChild(nodes.item(0));
            }
            var canvas = document.createElement('canvas');
            container.appendChild(canvas);
            if (_this.legend !== false && (_this.legend || 'auto') === 'auto') {
                cfg.options.onResize = _this._onResize.bind(_this);
            }
            _this._chart = new Chart(canvas, cfg);
            _this._onResize();
        });
    };
    ChartComponent.prototype._onResize = function () {
        var width = this._chart.chartArea.right - this._chart.chartArea.left;
        var height = this._chart.chartArea.bottom - this._chart.chartArea.top;
        var legendOptions = (this._chart.config.options || {}).legend || {};
        if (width < 120 || height < 120) {
            legendOptions.display = false;
        }
        else if (this._config.options.legend) {
            legendOptions.display = this._config.options.legend.display;
        }
    };
    ChartComponent.prototype._applyConfig = function () {
        var _this = this;
        var multiType = MULTI_SERIES_BY_DEFAULT.indexOf(this.type || 'bar') >= 0;
        this._config.type = this.type || 'bar';
        this._config.options = this._config.options || {};
        this._config.options.legend = this._config.options.legend || {};
        this._config.data = this._config.data || {};
        var ds = (this._config.data.datasets = _.cloneDeep(this.datasets || []));
        if (!(this._config.data.datasets || []).some(function (d) { return (d.label ? true : false); })) {
            if (multiType) {
                this._config.options.legend.display = false;
            }
        }
        var labels = (this._config.data.labels = _.cloneDeep(this.labels || []));
        _.set(this._config.options || {}, 'aspectRatio', this.ratio || 2);
        var legend = this.legend === false ? false : this.legend || 'auto';
        if (_.isString(legend) && ['top', 'right', 'bottom', 'left'].indexOf(legend) >= 0) {
            this._config.options.legend.position = legend;
        }
        else if (_.isBoolean(legend)) {
            this._config.options.legend.display = legend;
        }
        else if (_.isObject(legend)) {
            this._config.options.legend = _.cloneDeep(legend);
        }
        else if (legend === 'auto') {
            var multiPoints = ds.every(function (d) { return (d.data || []).length > 1; });
            var maxPoints = _.max(ds.map(function (d) { return (d.data || []).length; })) || 0;
            this._config.options.legend.display = (multiType && ds.length > 1) || (multiPoints && !multiType);
            this._config.options.legend.position = multiType && this.type !== 'radar' ? 'top' : 'right';
        }
        this._config.options.scales = {};
        if (this.currency) {
            var curr_1 = this.currency;
            if (multiType) {
                var axes = {
                    ticks: { callback: function (val) { return formatScale(val, curr_1); } }
                };
                if (ds.every(function (d) { return _this._isYAxisAllNumbers(d.data || []); })) {
                    if (this.type !== 'horizontalBar') {
                        this._config.options.scales.yAxes = [axes];
                    }
                    else {
                        this._config.options.scales.xAxes = [axes];
                    }
                }
            }
        }
        var timeScaleConfigured = false;
        if (this.type === 'line') {
            var isTimeScale = ds.every(function (d) {
                return (d.data || []).every(function (item) { return (item.x ? moment(item.x).isValid() : false); });
            });
            if (isTimeScale) {
                this._config.options.scales = this._config.options.scales || {};
                var minTime = _.min(_.flatMap(ds, function (d) { return d.data; }).map(function (p) { return moment(p.x); }));
                ds.every(function (d) {
                    return (d.data || []).every(function (item) { return (item.x ? moment(item.x).isValid() : false); });
                });
                this._config.options.scales.xAxes = [
                    {
                        type: 'time',
                        time: {
                            tooltipFormat: this.timeFormat || 'L',
                            min: minTime ? minTime.toISOString() : undefined
                        }
                    }
                ];
                timeScaleConfigured = true;
            }
        }
        if (ds.length === 0 || (ds[0].data || []).length === 0) {
            console.warn('ezy-chart: empty datasets. ');
        }
        else if ((ds[0].data || []).length > labels.length && !timeScaleConfigured) {
            console.warn('ezy-chart: wrong number of labels. ');
        }
        if (_.isEmpty(this._config.options.scales)) {
            this._config.options = _.pickBy(this._config.options, function (val, key) { return key !== 'scales'; });
        }
        this._config.options.tooltips = this._config.options.tooltips || {};
        this._config.options.tooltips.callbacks = this._config.options.tooltips.callbacks || {};
        this._config.options.tooltips.callbacks.label = getTooltipLabelCallBack(this.currency, this.percentage || false, this.digits);
        this._config.options.tooltips.callbacks.title = getTooltipTitleCallBack(this.type === 'horizontalBar');
        if (this.options) {
            _.merge(this._config.options, this.options);
        }
    };
    ChartComponent.prototype._isYAxisAllNumbers = function (data) {
        return data.every(function (d) { return !d || _.isNumber(d) || _.isNumber(d.y); });
    };
    ChartComponent.prototype._applyColors = function (colors, colorsFor, datasets) {
        if (colorsFor === 'auto') {
            if (MULTI_SERIES_BY_DEFAULT.indexOf(this.type || 'bar') >= 0) {
                colorsFor = 'series';
            }
            else {
                colorsFor = 'data';
            }
        }
        if (colorsFor === 'series') {
            var colorGroups = generateColorsBySeries(colors, datasets.length, this.type || 'bar');
            _.merge(datasets, colorGroups);
        }
        else if (colorsFor === 'data') {
            for (var _i = 0, datasets_1 = datasets; _i < datasets_1.length; _i++) {
                var ds = datasets_1[_i];
                var colorGroup = generateColorsByDataPoints(colors, (ds.data || []).length, this.type || 'bar');
                _.merge(ds, colorGroup);
            }
        }
    };
    tslib_1.__decorate([
        ViewChild('chartContainer', { read: ElementRef }),
        tslib_1.__metadata("design:type", ElementRef)
    ], ChartComponent.prototype, "_chartContainer", void 0);
    ChartComponent = tslib_1.__decorate([
        Component({
            selector: 'ezy-chart',
            template: "<div #chartContainer></div>",
            changeDetection: ChangeDetectionStrategy.OnPush
        }),
        tslib_1.__metadata("design:paramtypes", [NgZone])
    ], ChartComponent);
    return ChartComponent;
}(BaseChart));
export { ChartComponent };
//# sourceMappingURL=chart.component.js.map