import { Utils } from 'arm-common';
import p from 'prop-types';
import React, { useLayoutEffect, useMemo, useState } from 'react';

import { ChartContainer, useAm5, useAm5Colors, getRoot } from '../Am5.jsx';
import { AutoSize } from 'arm-core-layouts';


const classNamePrefix = 'armu_ai_chatbot-bar-chart';

export default function BarChart(props) {
    const { id, xAxis, yAxis, series, data } = props;

    const [chartId] = useState(id || Utils.uuid(classNamePrefix));
    const am5 = useAm5();
    const am5Colors = useAm5Colors();
    const allValues = useMemo(() => {
        if (data?.length) {
            if (series?.length) {
                const values = [];
                for (let item of data) {
                    for (let serie of series) {
                        if (!isNaN(item[serie.yAxis])) {
                            values.push(item[serie.yAxis]);
                        }
                    }
                }
                return values;
            } else {
                return data.map(d => d[yAxis]);
            }
        }
        return [];
    }, [data, series, yAxis]); 

    const minValue = Math.min(...allValues);

    useLayoutEffect(() => {
        if (am5 && data) {
            const root = getRoot(chartId);

            const chart = root.container.children.push(
                am5xy.XYChart.new(root, {
                    layout: root.verticalLayout
                })
            );

            const yAxisAm5 = chart.yAxes.push(
                am5xy.CategoryAxis.new(root, {
                    categoryField: xAxis,
                    renderer: am5xy.AxisRendererY.new(root, {
                        inversed: true,
                        cellStartLocation: 0.1,
                        cellEndLocation: 0.9
                    })
                })
            );

            yAxisAm5.data.setAll(data);

            const xAxisAm5 = chart.xAxes.push(
                am5xy.ValueAxis.new(root, {
                    renderer: am5xy.AxisRendererX.new(root, {
                        strokeOpacity: 0.1
                    }),
                    min: minValue < 0 ? minValue : 0,
                })
            );

            chart.set("colors", am5.ColorSet.new(root, {
                colors: am5Colors
            }));

            if (series?.length){
                const legend = chart.children.push(am5.Legend.new(root, {
                    centerX: am5.p50,
                    x: am5.p50,
                }));
    
                series.forEach(addSeries.bind({ root, chart, xAxisAm5, yAxisAm5, xAxis, data }));
                
                legend.data.setAll(chart.series.values);
            } else if (yAxis){
                addSeries.call({ root, chart, xAxisAm5, yAxisAm5, xAxis, data }, { yAxis });
            }

            const cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
                behavior: "zoomY"
            }));
            cursor.lineY.set("forceHidden", true);
            cursor.lineX.set("forceHidden", true);
        }
    }, [am5, allValues]);

    const height = useMemo(() => calcHeight(data, series), [data, series]);

    return (
        <ChartContainer id={chartId} style={{ height }} className={classNamePrefix} />
    );
}

BarChart.defaultProps = {
    id: '',
    xAxis: '',
    yAxis: '',
    series: [],
    data: null
}

BarChart.propTypes = {
    id: p.string,
    xAxis: p.string.isRequired,
    yAxis: p.string,
    series: p.arrayOf(p.shape({
        name: p.string,
        yAxis: p.string
    })),
    data: p.arrayOf(p.object).isRequired
}

function addSeries(seriesConfig) {
    const { root, chart, xAxisAm5, yAxisAm5, xAxis, data } = this;

    const { name, yAxis } = seriesConfig;

    const series = chart.series.push(
        am5xy.ColumnSeries.new(root, {
            name,
            minBulletDistance: 10,
            xAxis: xAxisAm5,
            yAxis: yAxisAm5,
            valueXField: yAxis,
            categoryYField: xAxis,
            sequencedInterpolation: true,
            tooltip: am5.Tooltip.new(root, {
                pointerOrientation: "horizontal",
                labelText: "[bold]{name}[/]\n{categoryY}: {valueX}"
            })
        })
    );

    series.columns.template.setAll({
        height: am5.p100,
        strokeOpacity: 0
    });


    series.bullets.push(function () {
        return am5.Bullet.new(root, {
            locationX: 1,
            locationY: 0.5,
            sprite: am5.Label.new(root, {
                centerY: am5.p50,
                text: "{valueX}",
                populateText: true
            })
        });
    });

    series.bullets.push(function () {
        return am5.Bullet.new(root, {
            locationX: 1,
            locationY: 0.5,
            sprite: am5.Label.new(root, {
                centerX: am5.p100,
                centerY: am5.p50,
                text: "{name}",
                fill: am5.color(0xffffff),
                populateText: true
            })
        });
    });

    series.data.setAll(data);
    series.columns.template.setAll({ cornerRadiusBR: 5, cornerRadiusTR: 5, strokeOpacity: 0 });
    series.appear();
}

function calcHeight(data, series) {
    const lineHeight = AutoSize.convertRemToPixels(3);
    const barHeight = AutoSize.convertRemToPixels(4);
    
    return (lineHeight * (data.length + 1)) + (barHeight * ((series?.length || 0) + 1)) + AutoSize.convertRemToPixels(5);
}