import { AfterViewInit, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { NbpBaseComponent } from '@isp/xdce-widget';
import * as d3 from 'd3';


export interface NbpFidDonutChartConfig {
    valueKey: string;
    labelKey: string;
    legendKey: string;
    colorKey?: string;
    colors?: string[];
    format?: (value: number) => string;
}

let counter = 0;

@Component({
    selector: 'nbp-fid-donut-chart',
    templateUrl: './nbp-fid-donut-chart.component.html',
    styleUrls: ['./nbp-fid-donut-chart.component.scss']
})
export class NbpFidDonutChartComponent extends NbpBaseComponent implements OnInit, AfterViewInit, OnChanges {
    constructor() {
        super();
        this.uniqueId = `nbp-fid-donut-chart-${++counter}`;
    }

    uniqueId: string = null;

    @Input() config: NbpFidDonutChartConfig = {
        valueKey: 'valore',
        labelKey: 'tipo',
        legendKey: 'name',
        colorKey: 'fill',
        colors: null
    };

    colors: string[] = [
        '#1F4E79',
        '#D3D3D3',
        '#6280a4',
        '#A9A9A9',
        '#3CB371',
        '#FFD700',
        '#FF6347',
        '#FF0000'
    ]

    @Input() data: any = [
        { name: 'Prodotti E-S-G', fill: '#1F4E79', tipo: 'Strumenti sostenibili', valore: 30 },
        { name: 'Prodotti non E-S-G', fill: '#D3D3D3', tipo: 'Strumenti non sostenibili', valore: 40 },
        { name: 'Altri prodotti', fill: '#6280a4', tipo: 'Altri strumenti', valore: 20 },
        { name: 'aaaaa', fill: '#A9A9A9', tipo: 'xxxxx', valore: 10 },
    ];

    formatter = (value: number): string => {
        const formatter = new Intl.NumberFormat('it-IT', {
            style: 'decimal',
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
        });

        return `${formatter.format(value)} %`;
    };

    svg: any;
    margin = { top: 10, right: 30, bottom: 30, left: 30 };
    width: number = 261;
    height: number = 140;
    radius: number = Math.min(this.width, this.height) / 4;
    d3colors: any;

    ngOnInit(): void {
        this.formatter = this.config.format || this.formatter;
        this.setColors();
    }

    ngAfterViewInit(): void {
        console.log('[NbpFidDonutChartComponent] ngAfterViewInit', this);
        this.createSvg();
        this.drawChart();
    }

    setColors(): void {
        if (this.config.colorKey) {
            this.colors = this.data.map((d: any, i: number): string => d[this.config.colorKey] ? d[this.config.colorKey] : this.colors[i]);
        } else if (this.config.colors) {
            this.colors = this.config.colors;
        }

        this.d3colors = d3
            .scaleOrdinal()
            .domain(this.data.map((d: any) => d[this.config.valueKey].toString()))
            .range(this.colors);
    }

    ngOnChanges(changes: SimpleChanges): void {
        if (changes['data'] || changes['config']) {
            this.ngOnInit();
            this.updateChart();
        }
    }

    createSvg(): void {
        console.log('createSvg', this);
        this.svg = d3
            .select(`figure#${this.uniqueId}`)
            .append('svg')
            .attr('viewBox', `0 0 ${this.width} 120`)
            .append('g')
            .attr(
                'transform',
                'translate(' + this.width / 1.9 + ',' + this.height / 2 + ')'
            );
    }

    drawChart(): void {
        const pie = d3
            .pie<any>()
            .sort(null)
            .value((d: any) => Number(d[this.config.valueKey]));

        const data_ready = pie(this.data);

        console.log('data_ready', data_ready);

        const arc = d3
            .arc()
            .innerRadius(this.radius * 0.4)
            .outerRadius(this.radius * 0.7);

        const outerArc = d3
            .arc()
            .innerRadius(this.radius * 0.9)
            .outerRadius(this.radius * 0.9);

        this.svg
            .selectAll('allSlices')
            .data(data_ready)
            .enter()
            .append('path')
            .attr('d', arc)
            .attr('fill', (d: any) => this.d3colors(d.data[this.config.valueKey]))
            .attr('stroke', 'white')
            .style('stroke-width', '0px');

        this.svg
            .selectAll('allPolylines')
            .data(data_ready)
            .enter()
            .append('polyline')
            .attr('stroke', '#656565')
            .style('fill', 'none')
            .attr('stroke-width', 1)
            .attr('points', (d: any) => {
                const posA = arc.centroid(d);
                const posB = outerArc.centroid(d);
                const midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
                posB[0] = this.radius * 0.95 * (midangle < Math.PI ? 1 : -1);
                return [posA, posB];
            });

        // Draw labels
        this.svg
            .selectAll('allLabels')
            .data(data_ready)
            .enter()
            .append('text')
            .style('fill', '#656565')
            .text((d: any) => `${d.data[this.config.labelKey]} (${this.formatter(d.data[this.config.valueKey])})`)
            .attr('font-size', '6px')
            .attr('transform', (d: any) => {
                const pos = outerArc.centroid(d);
                const midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
                pos[0] = this.radius * 0.99 * (midangle < Math.PI ? 1 : -1);
                return 'translate(' + pos + ')';
            })
            .style('text-anchor', (d: any) => {
                const midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
                return midangle < Math.PI ? 'start' : 'end';
            });
    }

    private updateChart() {
        d3.select(`#${this.uniqueId}`).selectAll("*").remove();
        this.createSvg();
        this.drawChart();
    }
}