/*
 * Copyright 2021 - All rights reserved.
 * Rodrigo Tapia-McClung
 *
 * January 2021
 */

/* globals updateBarChartOnHover, barChartData, am4charts, am4core, am4themes_animated, yearList */
/* export makeRadarChart, makeLineChart, makeAreaChart, makeBarChart */

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
const  grijalva_theme = target => {
    if (target instanceof am4core.ColorSet) {
        target.list = [
            am4core.color("#00c5ff"),
            am4core.color("#ff5500"),
            am4core.color("#98e600")
        ];
    }
}

const  customizeGrip = grip => {
    // Remove default grip image
    grip.icon.disabled = true;

    // Disable background
    grip.background.disabled = true;

    // Add rotated rectangle as bi-di arrow
    let img = grip.createChild(am4core.Rectangle);
    img.width = 7;
    img.height = 7;
    img.fill = am4core.color("#999");
    img.rotation = 45;
    img.align = "center";
    img.valign = "middle";
}

// Themes begin
am4core.useTheme(am4themes_animated);
am4core.useTheme(grijalva_theme);
//let mainTextColor = getComputedStyle(document.body).getPropertyValue("--main-text-color");
// Themes end

let mainTextColor = getComputedStyle(document.body).getPropertyValue("--main-text-color");

const makeRadarSeries = (chart, value, category, name, color) => {
    let radarSeries = chart.series.push(new am4charts.RadarSeries());
    radarSeries.dataFields.valueY = value;
    radarSeries.dataFields.categoryX = category;
    radarSeries.strokeWidth = 1.5;
    radarSeries.name = String(name);
    //radarSeries.connect = false;
    //radarSeries.connectEnds = false;
    radarSeries.stroke = am4core.color(color);
    radarSeries.tooltip.getFillFromObject = false;
    radarSeries.tooltipText = "[bold] {name.formatNumber(\"####\")}: [/]{valueY.formatNumber('#,###.0')} Ha[/]";
    radarSeries.tooltip.background.fill = am4core.color(color);
}

const makeRadarRange = (axis, start, end, color, span) => {
    let radarRange = axis.axisRanges.create();
    radarRange.category = start;
    radarRange.endcategory = end;
    radarRange.axisFill.fill = am4core.color(color);
    radarRange.axisFill.fillOpacity = 0.4;
    radarRange.grid.strokeOpacity = 0;
    radarRange.locations.endCategory = span ? span : "";
}

const makeLineAxisAndSeries = (chart, field, name, opposite, bullet) => {
    let lineValueAxis = chart.yAxes.push(new am4charts.ValueAxis());
    lineValueAxis.fontSize = 10;

    if (chart.yAxes.indexOf(lineValueAxis) != 0) {
        lineValueAxis.syncWithAxis = chart.yAxes.getIndex(0);
    }

    let lineSeries = chart.series.push(new am4charts.LineSeries());
    lineSeries.dataFields.valueY = field;
    lineSeries.dataFields.dateX = "date";
    lineSeries.strokeWidth = 2;
    lineSeries.yAxis = lineValueAxis;
    lineSeries.name = name;
    lineSeries.tooltipText = "[bold]{name}: [/]{valueY.formatNumber('#,###.0')} Ha[/]";
    lineSeries.tooltipText.fontSize = 10;
    lineSeries.tensionX = 0.8;
    lineSeries.showOnInit = true;

    lineValueAxis.renderer.line.strokeOpacity = 1;
    lineValueAxis.renderer.line.strokeWidth = 2;
    lineValueAxis.renderer.line.stroke = lineSeries.stroke;
    lineValueAxis.renderer.labels.template.fill = lineSeries.stroke;
    lineValueAxis.renderer.opposite = opposite;
}

const makeDateRange = (axis, start, width, color) => {
    yearList.forEach( y => {
        let range = axis.axisRanges.create();
        range.date = new Date(y, start, 1, 0, 0, 0);
        range.endDate = new Date(y, start + width, 1, 0, 0, 0);
        range.axisFill.fill = am4core.color(color);
        range.axisFill.fillOpacity = 0.4;
    });
}

const makeAreaSeries = (chart, field, name) => {
    let areasSeries = chart.series.push(new am4charts.LineSeries());
    areasSeries.dataFields.dateX = "date";
    areasSeries.name = name;
    areasSeries.dataFields.valueY = field;
    areasSeries.tooltipText = "[bold]{name}: [/]{valueY.formatNumber('#,###.#')} Ha";
    //areasSeries.tooltip.background.fill = am4core.color("#FFF");
    areasSeries.tooltip.getStrokeFromObject = true;
    areasSeries.tooltip.background.strokeWidth = 3;
    //areasSeries.tooltip.getFillFromObject = false;
    areasSeries.fillOpacity = 0.6;
    areasSeries.strokeWidth = 2;
    areasSeries.stacked = true;
    return areasSeries;
}

const makeBarSeries = (chart, field, name) => {
    let barSeries = chart.series.push(new am4charts.ColumnSeries());
    barSeries.dataFields.valueY = field;
    barSeries.dataFields.categoryX = "grupo";

    barSeries.name = name;
    barSeries.columns.template.tooltipText = "[underline][bold]Menor a [bold]{categoryX.formatNumber('#,###.#')} Ha[/]: {valueY.formatNumber('#,###.#')} cuerpos[/]";
    barSeries.columns.template.height = am4core.percent(100);
    barSeries.sequencedInterpolation = true;

    let barValueLabel = barSeries.bullets.push(new am4charts.LabelBullet());
    barValueLabel.label.text = "{valueY}";
    barValueLabel.label.horizontalCenter = "middle";
    barValueLabel.label.dx = 3;
    barValueLabel.label.dy = -5;
    barValueLabel.label.hideOversized = false;
    barValueLabel.label.truncate = false;
    barValueLabel.fontSize = 10;
    //barValueLabel.label.fill = am4core.color(mainTextColor);
    barValueLabel.label.fill = am4core.color("#fff");
}

const makeRadarChart = (data, months, years) => {
    let radarChart = am4core.create("radarChart", am4charts.RadarChart);

    let radarTitle = radarChart.titles.create();
    radarTitle.text = "Superficie total por año";
    radarTitle.fontSize = 10;
    radarTitle.marginBottom = 10;
    radarTitle.fill = am4core.color(mainTextColor);

    radarChart.data = data;

    /* Create axes */
    let radarCategoryAxis = radarChart.xAxes.push(new am4charts.CategoryAxis());
    radarCategoryAxis.dataFields.category = "month";
    radarCategoryAxis.fontSize = 10;
    radarCategoryAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
    radarCategoryAxis.renderer.grid.template.stroke = am4core.color(mainTextColor);

    let radarValueAxis = radarChart.yAxes.push(new am4charts.ValueAxis());
    radarValueAxis.extraMin = 0.2;
    radarValueAxis.extraMax = 0.2;
    radarValueAxis.tooltip.disabled = true;
    radarValueAxis.fontSize = 10;
    radarValueAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
    radarValueAxis.renderer.grid.template.stroke = am4core.color(mainTextColor);
    //radarValueAxis.renderer.labels.template.fontSize = 15;

    /* Create and configure series */
    let seriesColor = ["#F98293", "#2AC2BB", "#FDA259"];
    years.forEach( (year, i) => {
        makeRadarSeries(radarChart, year, "month", year, seriesColor[i]);
    });

    radarChart.scrollbarX = new am4core.Scrollbar();
    radarChart.scrollbarX.minHeight = 1;
    radarChart.scrollbarX.parent = radarChart.bottomAxesContainer;
    radarChart.scrollbarY = new am4core.Scrollbar();
    radarChart.scrollbarY.minWidth = 1;
    customizeGrip(radarChart.scrollbarX.startGrip);
    customizeGrip(radarChart.scrollbarX.endGrip);
    customizeGrip(radarChart.scrollbarY.startGrip);
    customizeGrip(radarChart.scrollbarY.endGrip);

    let radarRangeColors = ["#E1DBC8", "#595952", "#838278", "#B1AE9F"];
    makeRadarRange(radarCategoryAxis, "enero", "marzo", radarRangeColors[0], 2);
    makeRadarRange(radarCategoryAxis, "marzo", "mayo", radarRangeColors[1], 2);
    makeRadarRange(radarCategoryAxis, "mayo", "septiembre", radarRangeColors[2], 4);
    makeRadarRange(radarCategoryAxis, "septiembre", "diciembre", radarRangeColors[3], 3);
    makeRadarRange(radarCategoryAxis, "diciembre", "diciembre", radarRangeColors[0], 1);

    radarChart.cursor = new am4charts.RadarCursor();
    radarChart.cursor.fullWidthLineX = true;
    radarChart.cursor.lineX.strokeWidth = 1;
    radarChart.cursor.lineX.fill = am4core.color("#8F3985");
    radarChart.cursor.lineX.fillOpacity = 0.1;
    radarChart.cursor.xAxis = radarCategoryAxis;

    //radarCategoryAxis.cursorTooltipEnabled = false;
    //FIXME: some months are not showing the appropriate name on tooltip on hover
    // in the meantime this is a way around to fix cursor columns and not show wrong
    // month tooltips
    radarChart.cursor.events.on("cursorpositionchanged", ev => {
        let categoryAxis = ev.target.chart.xAxes.getIndex(0);
        categoryAxis.tooltip.hide();
    });
    //radarCategoryAxis.startLocation = -0.0000001;
    //radarCategoryAxis.endLocation = 1;

    // add line legend
    radarChart.legend = new am4charts.Legend();
    radarChart.legend.fontSize = 10;
    radarChart.legend.labels.template.fill = am4core.color(mainTextColor);
    radarChart.legend.itemContainers.template.paddingTop = 0;
    radarChart.legend.itemContainers.template.paddingBottom = 0;

    let legenddata = [{ name: "Estiaje", fill: am4core.color("#595952") },
        { name: "Tropical", fill: am4core.color("#838278") },
        { name: "Tropical-Invernal", fill: am4core.color("#B1AE9F") },
        { name: "Invernal", fill: am4core.color("#E1DBC8") }
    ];

    // add second legend
    radarChart.legend = new am4charts.Legend();
    radarChart.legend.data = legenddata;
    radarChart.legend.fontSize = 10;
    radarChart.legend.labels.template.fill = am4core.color(mainTextColor);
    radarChart.legend.maxColumns = 2;

    let markerTemplate = radarChart.legend.markers.template;
    markerTemplate.width = 20;
    markerTemplate.height = 20;
    radarChart.legend.itemContainers.template.paddingTop = 0;

    // remove legend interactivity
    radarChart.legend.itemContainers.template.clickable = false
    radarChart.legend.itemContainers.template.focusable = false
    radarChart.legend.itemContainers.template.cursorOverStyle = am4core.MouseCursorStyle.default;
    
}

const makeLineChart = (data) => {

    let lineChart = am4core.create("lineChart", am4charts.XYChart);
    let lineTitle = lineChart.titles.create();
    lineTitle.text = "Superficie por tipo de cuerpo";
    lineTitle.fontSize = 10;
    lineTitle.marginBottom = 15;
    lineTitle.fill = am4core.color(mainTextColor);

    lineChart.data = data;

    let lineDateAxis = lineChart.xAxes.push(new am4charts.DateAxis());
    lineDateAxis.renderer.minGridDistance = 50;
    lineDateAxis.fontSize = 10;
    lineDateAxis.renderer.labels.template.fill = am4core.color(mainTextColor);

    // Create series
    makeLineAxisAndSeries(lineChart, "permanente", "Agua permanente", false, "circle");
    makeLineAxisAndSeries(lineChart, "temporal", "Áreas temporalmente inundadas", true, "triangle");
    makeLineAxisAndSeries(lineChart, "vegetacion", "Suelos húmedos-vegetación acuática", true, "rectangle");

    // create line ranges
    makeDateRange(lineDateAxis, 0, 2, "#E1DBC8");
    makeDateRange(lineDateAxis, 2, 2, "#595952");
    makeDateRange(lineDateAxis, 4, 4, "#838278");
    makeDateRange(lineDateAxis, 8, 3, "#B1AE9F");
    makeDateRange(lineDateAxis, 11, 1, "#E1DBC8");  // FIXME: this range shows a small line separator between Dec-Jan

    // Add cursor
    lineChart.cursor = new am4charts.XYCursor();
    lineChart.cursor.fullWidthLineX = true;
    lineChart.cursor.lineX.strokeWidth = 1;
    lineChart.cursor.lineX.fill = am4core.color("#8F3985");
    lineChart.cursor.lineX.fillOpacity = 0.1;
    lineChart.cursor.xAxis = lineDateAxis;
    lineChart.scrollbarX = new am4core.Scrollbar();
    lineChart.scrollbarX.minHeight = 1;
    lineChart.scrollbarX.parent = lineChart.bottomAxesContainer;
    customizeGrip(lineChart.scrollbarX.startGrip);
    customizeGrip(lineChart.scrollbarX.endGrip);
    // Style scrollbar
}

const makeAreaChart = (data) => {
    let areaChart = am4core.create("areaChart", am4charts.XYChart);
    let areaTitle = areaChart.titles.create();
    areaTitle.text = "Superficie acumulada";
    areaTitle.fontSize = 10;
    areaTitle.marginBottom = 15;
    areaTitle.fill = am4core.color(mainTextColor);

    areaChart.data = data;

    let areaDateAxis = areaChart.xAxes.push(new am4charts.DateAxis());
    areaDateAxis.renderer.minGridDistance = 50;
    areaDateAxis.fontSize = 10;
    areaDateAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
    // change following values to change where series start and end in graph
    //areaDateAxis.startLocation = 0.45;
    //areaDateAxis.endLocation = 0.55;
    areaDateAxis.baseInterval = {
        timeUnit: "month",
        count: 1
    }

    let areaValueAxis = areaChart.yAxes.push(new am4charts.ValueAxis());
    areaValueAxis.tooltip.disabled = true;
    areaValueAxis.fontSize = 10;
    areaValueAxis.renderer.labels.template.fill = am4core.color(mainTextColor);

    // Create series
    makeAreaSeries(areaChart, "permanente", "Agua permanente");
    makeAreaSeries(areaChart, "temporal", "Áreas temporalmente inundadas");
    makeAreaSeries(areaChart, "vegetacion", "Suelos húmedos-vegetación acuática");

    // create line ranges
    makeDateRange(areaDateAxis, 0, 2, "#E1DBC8");
    makeDateRange(areaDateAxis, 2, 2, "#595952");
    makeDateRange(areaDateAxis, 4, 4, "#838278");
    makeDateRange(areaDateAxis, 8, 3, "#B1AE9F");
    makeDateRange(areaDateAxis, 11, 1, "#E1DBC8");

    areaChart.cursor = new am4charts.XYCursor();
    areaChart.cursor.fullWidthLineX = true;
    areaChart.cursor.lineX.strokeWidth = 1;
    areaChart.cursor.lineX.fill = am4core.color("#8F3985");
    areaChart.cursor.lineX.fillOpacity = 0.1;
    areaChart.cursor.xAxis = areaDateAxis;
    areaChart.scrollbarX = new am4core.Scrollbar();
    areaChart.scrollbarX.minHeight = 1;
    areaChart.scrollbarX.parent = areaChart.bottomAxesContainer;
    customizeGrip(areaChart.scrollbarX.startGrip);
    customizeGrip(areaChart.scrollbarX.endGrip);
    //areaChart.scrollbarX.position = "bottom";

    /* Set up cursor behavior */
    let previousDate = "";
    areaChart.cursor.events.on("cursorpositionchanged", ev => {
        let dateAxis = ev.target.chart.xAxes.getIndex(0);
        let yy = dateAxis.positionToDate(dateAxis.toAxisPosition(ev.target.xPosition)).getFullYear().toString();
        let mm = dateAxis.positionToDate(dateAxis.toAxisPosition(ev.target.xPosition)).getMonth().toString();
        let month = 0;
        if (mm < 9) { month = "0" + (parseInt(mm) + 1).toString(); } else {
            month = parseInt(mm) + 1;
            month.toString();
        }
        let filterDate = new Date(`${yy}-${month}`).setUTCHours(6, 0, 0);
        // only update chart when dates in cursor change month
        if (filterDate.valueOf() != previousDate.valueOf()) {
            previousDate = filterDate;
            let barData = [].concat.apply([], barChartData);
            updateBarChartOnHover(filterDate, barData); // FIXME: when calling this update, bar chart may not exist yet
        }
    });
}

const makeBarChart = (data) => {
    let barChart = am4core.create("barChart", am4charts.XYChart);

    let barTitle = barChart.titles.create();
    barTitle.text = "Conteo por tipo de cuerpo";
    barTitle.fontSize = 10;
    barTitle.marginBottom = 5;
    barTitle.fill = am4core.color(mainTextColor);

    barChart.data = data;

    // Create axes
    let barCategoryAxis = barChart.xAxes.push(new am4charts.CategoryAxis());
    barCategoryAxis.dataFields.category = "grupo";
    barCategoryAxis.numberFormatter.numberFormat = "#,###.#";
    barCategoryAxis.renderer.inversed = true;
    barCategoryAxis.renderer.grid.template.location = 0;
    barCategoryAxis.renderer.cellStartLocation = 0.1;
    barCategoryAxis.renderer.cellEndLocation = 0.9;
    barCategoryAxis.fontSize = 10;
    barCategoryAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
    barCategoryAxis.title.text = "Superficie (Ha)";
    barCategoryAxis.title.fill = am4core.color(mainTextColor);

    let barValueAxis = barChart.yAxes.push(new am4charts.ValueAxis());
    //barValueAxis.renderer.opposite = true;
    //barValueAxis.calculateTotals = true
    barValueAxis.fontSize = 10;
    barValueAxis.extraMax = 0.05;
    barValueAxis.renderer.labels.template.fill = am4core.color(mainTextColor);
    barValueAxis.max = 1250; // TODO: compute max value from data

    // crate series
    makeBarSeries(barChart, "ap", "Agua permanente");
    makeBarSeries(barChart, "at", "Áreas temporalmente inundadas");
    makeBarSeries(barChart, "av", "Suelos húmedos-vegetación acuática");
}