/*
 * Copyright 2020 - All rights reserved.
 * Rodrigo Tapia-McClung
 *
 * June 2020
 */

/* globals am4core, am4charts, am4themes_animated, intervals */

let minValue, maxValue;
let mainTextColor = getComputedStyle(document.body).getPropertyValue("--main-text-color");
let cellbgColor = getComputedStyle(document.body).getPropertyValue("--main-bg-color");

// amChart
am4core.ready(function() {

    // Themes begin
    am4core.useTheme(am4themes_animated);
    am4core.options.autoSetClassName = true;
    // Themes end

    let chart = am4core.create("topLeftChart", am4charts.XYChart);
    chart.maskBullets = false;

    let title = chart.titles.create();
    title.fill = am4core.color(mainTextColor);
    title.fontSize = 15;
    title.marginBottom = 15;

    chart.events.on("beforedatavalidated", (ev) => {
        let option = $("#indicatorSelect").val();
        let optionTitle = $("#indicatorSelect option:selected").text();

        title.text = optionTitle;

        let data = ev.target.data;
        minValue = d3.min(data, d => { return d.flowCount || Infinity; });
        maxValue = d3.max(data, d => { return d.flowCount; });
        //heatLegend.minValue = minValue;
        //heatLegend.maxValue = maxValue;
        heatLegend.minValue = 0;
        heatLegend.maxValue = intervals[option].values[intervals[option].values.length - 1];

        // update heatLegend colors
        let heatColors = [];
        ["#333", ...intervals[option].colors].forEach(c => heatColors.push(am4core.color(c)));
        heatLegend.minColor = heatColors[0];
        heatLegend.maxColor = heatColors[intervals[option].colors.length - 1];

        let checkConditions = [minValue, ...intervals[option].values];
        let lastValue = intervals[option].values[intervals[option].values.length - 1]

        // Override heatLegend gradient
        let gradient = new am4core.LinearGradient();
        heatColors.forEach( (color, index) => {
            // addColor(color, opacity, offset) use offset to put colors in proper alignment
            gradient.addColor(color, undefined, (checkConditions[index] - checkConditions[0]) / lastValue);
        });

        heatLegend.markers.clear();
        heatLegend.markers.template.adapter.add("fill", () => {
            return gradient;
        });

        // update cell colors
        columnTemplate.adapter.add("fill", (fill, column) => {
            let workingValue = column.dataItem.values["value"].workingValue;
            // use min max values calculated from data on beforedatavalidated
            if (am4core.type.isNumber(workingValue)) {
                checkConditions.forEach((condition, index) => {
                    if (index < checkConditions.length - 1) {
                        if (workingValue >= condition && workingValue <= checkConditions[index + 1]) {
                            //console.log(`${workingValue} entre ${condition} y ${checkConditions[index+1]}`);
                            fill = new am4core.Color(
                                am4core.colors.interpolate(
                                    heatColors[index].rgb,
                                    heatColors[index + 1].rgb,
                                    workingValue
                                )
                            );
                            //console.log(workingValue, intervals.ocupadosDesde.colors[index]);
                        } else if (workingValue < checkConditions[0]) {
                            fill = new am4core.color(cellbgColor);
                        }
                    }
                });
            }
            return fill;
        });
    });

    let xAxis = chart.xAxes.push(new am4charts.CategoryAxis()),
        yAxis = chart.yAxes.push(new am4charts.CategoryAxis());

    xAxis.dataFields.category = "xVar";
    yAxis.dataFields.category = "yVar";

    xAxis.renderer.grid.template.disabled = true;
    xAxis.renderer.minGridDistance = 10;
    xAxis.renderer.opposite = true;
    xAxis.title.text = "[bold]Origen[/]";
    xAxis.title.fontSize = 15
    xAxis.title.paddingBottom = -10;
    xAxis.title.paddingTop = -10;
    xAxis.renderer.labels.template.truncate = true;

    // on axis size change, resize labels
    //FIXME: 80% hack should be better
    xAxis.events.on("sizechanged", ev => {
        let axis = ev.target;
        let cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
        axis.renderer.labels.template.maxWidth = 2 * Math.ceil(cellWidth) * 0.8;
    });

    // on data change change, resize labels
    //FIXME: 80% hack should be better
    xAxis.events.on("datarangechanged", ev => {
        let axis = ev.target;
        let cellWidth = axis.pixelWidth / (axis.endIndex - axis.startIndex);
        axis.renderer.labels.template.maxWidth = 2 * Math.ceil(cellWidth) * 0.8;
    });

    xAxis.renderer.labels.template.fontSize = 12;
    xAxis.tooltip.fontSize = 13;
    xAxis.title.fill = am4core.color(mainTextColor);
    xAxis.renderer.labels.template.fill = am4core.color(mainTextColor);

    yAxis.renderer.grid.template.disabled = true;
    yAxis.renderer.inversed = true;
    yAxis.renderer.minGridDistance = 1;
    yAxis.title.text = "[bold]Destino[/]";
    yAxis.title.fontSize = 15
    yAxis.title.paddingBottom = -10;
    yAxis.renderer.labels.template.truncate = true;
    yAxis.renderer.labels.template.maxWidth = 120;
    yAxis.renderer.labels.template.fontSize = 12;
    yAxis.tooltip.fontSize = 13;
    yAxis.title.fill = am4core.color(mainTextColor);
    yAxis.renderer.labels.template.fill = am4core.color(mainTextColor);

    let series = chart.series.push(new am4charts.ColumnSeries());
    series.dataFields.categoryX = "xVar";
    series.dataFields.categoryY = "yVar";
    series.dataFields.value = "flowCount";
    series.sequencedInterpolation = true;
    series.cursorTooltipEnabled = false;
    series.defaultState.transitionDuration = 3000;
    // Add cursor
    chart.cursor = new am4charts.XYCursor();
    chart.cursor.behavior = "none";
    chart.cursor.xAxis = xAxis;
    chart.cursor.yAxis = yAxis;
    chart.cursor.fullWidthLineX = true;
    chart.cursor.fullWidthLineY = true;
    chart.cursor.lineX.fill = am4core.color(mainTextColor);
    chart.cursor.lineX.fillOpacity = 0.05;
    chart.cursor.lineY.fill = am4core.color(mainTextColor);
    chart.cursor.lineY.fillOpacity = 0.05;

    let bgColor = new am4core.InterfaceColorSet().getFor("background");

    let columnTemplate = series.columns.template;
    columnTemplate.applyOnClones = true;
    columnTemplate.strokeWidth = 2;
    columnTemplate.strokeOpacity = 0;
    columnTemplate.stroke = bgColor;
    columnTemplate.tooltipHTML = `<div class="amcharttooltip">{xVar} <i class="fas fa-long-arrow-alt-right"></i> {yVar}: {value.workingValue.formatNumber("#,###")}</div>`;
    columnTemplate.width = am4core.percent(100);
    columnTemplate.height = am4core.percent(100);
    columnTemplate.column.cornerRadius(4, 4, 4, 4);
    columnTemplate.column.padding(0.5, 0.5, 0.5, 0.5);

    columnTemplate.adapter.add("strokeWidth", (width, column) => {
        let workingValue = column.dataItem.values["value"].workingValue;
        if (am4core.type.isNumber(workingValue)) {
            width = workingValue != 0 ? 1 : 0;
        }
        return width;
    });

    // heat legend
    //let heatLegend = chart.createChild(am4charts.HeatLegend);
    let heatLegend = chart.bottomAxesContainer.createChild(am4charts.HeatLegend);
    heatLegend.marginTop = 5;
    heatLegend.width = am4core.percent(100);
    heatLegend.markerContainer.minHeight = 20;
    heatLegend.markers.template.minHeight = 20;
    heatLegend.series = series;
    heatLegend.valueAxis.renderer.labels.template.fontSize = 12;
    heatLegend.valueAxis.renderer.minGridDistance = 35;
    heatLegend.valueAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
    heatLegend.valueAxis.renderer.labels.template.paddingTop = 5;
    heatLegend.valueAxis.tooltip.fontSize = 13;

    // heatLegend min, max, colors and fill are modified above using adapters

    // when chart changes size, what happens with heatLegend fill
    heatLegend.markers.template.events.on("sizechanged", event => {
        event.target.fill = event.target.fill;
    });

    // heat legend behavior

    const handleHover = column => {
        if (!isNaN(column.dataItem.value)) {
            column.strokeWidth = 2;
            column.strokeOpacity = 0.2;
            heatLegend.valueAxis.showTooltipAt(column.dataItem.value);
        } else {
            column.strokeWidth = 0;
            column.strokeOpacity = 0;
            heatLegend.valueAxis.hideTooltip();
        }
    }

    series.columns.template.events.on("over",  event => {
        handleHover(event.target);
    });

    series.columns.template.events.on("hit", event => {
        handleHover(event.target);
    });

    series.columns.template.events.on("out", event => {
        event.target.strokeWidth = 0;
        event.target.strokeOpacity = 0;
        heatLegend.valueAxis.hideTooltip();
    });

    chart.responsive.enabled = true;


    // chord diagram

    let cd_chart = am4core.create("bottomLeftChart", am4charts.ChordDiagram);

    let cd_title = cd_chart.titles.create();

    cd_title.fill = am4core.color(mainTextColor);
    cd_title.fontSize = 13;
    cd_title.align = "left";
    cd_title.marginBottom = 20;
    cd_title.paddingLeft = 10;

    cd_chart.events.on("beforedatavalidated", () => {
        let optionTitle = $("#indicatorSelect option:selected").text();
        cd_title.text = "[bold]Conectividad origen - destino entre \n" + optionTitle.toLowerCase();
    });

    cd_chart.dataFields.fromName = "xVar";
    cd_chart.dataFields.toName = "yVar";
    cd_chart.dataFields.value = "flowCount";

    // make nodes draggable
    let nodeTemplate = cd_chart.nodes.template;
    nodeTemplate.readerTitle = "Oculta/muestra para reorganizar la red"; //"Click to show/hide or drag to rearrange";
    nodeTemplate.showSystemTooltip = true;

    let nodeLink = cd_chart.links.template;
    let bullet = nodeLink.bullets.push(new am4charts.CircleBullet());
    bullet.fillOpacity = 0.8;
    bullet.circle.radius = 3;
    bullet.locationX = 0.5;

    // create animations

    const animateBullet = (bullet) => {
        let duration = cd_chart.links.length * Math.random() + 3000;
        let animation = bullet.animate([{ property: "locationX", from: 0, to: 1.05 }], duration);
        animation.events.on("animationended", event => {
            animateBullet(event.target.object);
        });
    }

    nodeTemplate.events.on("ready", () => {
        for (let i = 0; i < cd_chart.links.length; i++) {
            let link = cd_chart.links.getIndex(i);
            let bullet = link.bullets.getIndex(0);

            animateBullet(bullet);
        }
    });

    let label = nodeTemplate.label;
    label.relativeRotation = 90;
    label.fontSize = 10;
    label.fill = am4core.color(mainTextColor);

    cd_chart.responsive.enabled = true;

}); // end am4core.ready()