import { createGraph, switchPlot } from "../core";
import { months, monthsPretty, prettyModeNames } from "../staticData/constants";
import { addConfigField, clearChildren, getData, prettyMonthName } from "../utils";
import { Graph } from "./graph";

export class CorporationBreakdown implements Graph {
    id = "corpBreakdown";
    displayName = "Corp Breakdown";

    configFieldIDs = ["chartType", "metric", "month", "companyName"];
    loadedData: any;
    urlParams: any;

    constructor(loadedData: any, urlParams: any)
    {
        this.loadedData = loadedData;
        this.urlParams = urlParams;
    }

    setConfigs(useURLParams?: boolean)
    {
        const updateFunc = function() {switchPlot();}

        const configDiv = document.getElementById("selectorSubtypes");
        if(configDiv)
        {
            clearChildren(configDiv);
        }

        configDiv?.appendChild(addConfigField("select", "chartType", "Chart Type: ", {prettyValues: ["Bar", "Pie", "Treemap"], values: ["bar", "pie", "treemap"]}, useURLParams ? this.urlParams.chartType : "treemap", updateFunc, "-30px"));
        configDiv?.appendChild(addConfigField("select", "metric", "Metric: ", {prettyValues: ["Volume", "Profit", "Bases", "Ships"], values: ["volume", "profit", "bases", "ships"]}, useURLParams ? this.urlParams.metric : undefined, updateFunc));
        configDiv?.appendChild(addConfigField("select", "month", "Month: ", {prettyValues: monthsPretty, "values": months}, useURLParams && this.urlParams.month ? this.urlParams.month : months[months.length - 1], updateFunc));
        configDiv?.appendChild(addConfigField("input", "companyName", "Corp Code: ", undefined, useURLParams ? this.urlParams.companyName : undefined, updateFunc, "-29px"));
        
    }

    async generatePlot(configValues: any, plotContainerID: string)
    {
        if(!configValues.companyName || configValues.companyName == ""){return;}
        var fileName;
        switch(configValues.metric)
        {
            case "bases":
                fileName = "base"
                break;
            case "ships":
                fileName = "ship"
                break;
            default:
                fileName = "company"
        }
        // Get Company Data
        const companyData = await getData(this.loadedData, fileName, configValues.month);
        const dataset = configValues.metric == "bases" || configValues.metric == "ships" ? companyData : companyData.totals;

        const knownCompanies = await getData(this.loadedData, "knownCompanies");

        var companyName: string;

        const parentCorps = await getData(this.loadedData, 'parentCorps');
        companyName = configValues.companyName.toUpperCase();
        const corpData = {} as any;

        // Return if company data not defined for that month
        if(!companyData)
        {
            console.error("Data type not defined for this month.")
            return;
        }
        
        Object.keys(dataset).forEach(id => {
            const companyObj = knownCompanies[id]
            if(companyObj && (companyObj.Corporation == companyName || parentCorps[companyObj.Corporation] == companyName))
            {
                const indivCompanyData = dataset[id];
                const name = companyObj['Username'];
                corpData[name] = indivCompanyData;
            }
        });

        if(Object.keys(corpData).length == 0){return;}

        // Parse Data
        var catData = [] as number[]; // Y-axis of chart
        var categories = [] as any[];  // X-axis of chart
        var totalValue = 0; // Total of metric
        
        Object.keys(corpData).forEach((name: string) => {
            const metric = corpData[name][configValues.metric];
            if(metric < 0 && (configValues.chartType == "treemap")){return;}
            totalValue += metric;

            catData.push(metric);
            categories.push(name);

        });

        // Sort data from largest to smallest categories
        const indices = Array.from(categories.keys());
        indices.sort((a, b) => catData[b] - catData[a]);
        catData = indices.map(i => catData[i]);
        categories = indices.map(i => categories[i]);

        // Create graph
        const titles = {
		    'profit': 'Production Profit Breakdown of ',
		    'volume': 'Production Volume Breakdown of ',
            'bases': 'Base Breakdown of ',
            'ships': 'Ship Breakdown of '
	    } as any;
        const hoverTemplates = {
            'profit': '%{label}<br>$%{value:,.3~s}/day<br>%{percentEntry:.2%}<extra></extra>',
            'volume': '%{label}<br>$%{value:,.3~s}/day<br>%{percentEntry:.2%}<extra></extra>',
            'bases': '%{label}<br>%{value:,.3~s}<br>%{percentEntry:.2%}<extra></extra>',
            'ships': '%{label}<br>%{value:,.3~s}<br>%{percentEntry:.2%}<extra></extra>'
        } as any;

        if(configValues.chartType == "treemap")
        {
            
            const parents = categories.map(m => "Total");
            categories.push("Total");
            catData.push(totalValue);
            parents.push('');

            // Make graph
            createGraph(plotContainerID, [{
                labels: categories, 
                values: catData, 
                parents: parents, 
                type: 'treemap', 
                maxdepth: 2, 
                branchvalues: 'total',
                tiling: {
                    pad: 0,
                },
                textposition: 'middle center',
                hovertemplate: hoverTemplates[configValues.metric]}],
            {
                width: this.urlParams.hideOptions !== undefined ? undefined : 800,
                height: this.urlParams.hideOptions !== undefined ? undefined : 400,
                autosize: this.urlParams.hideOptions !== undefined,
                ...(this.urlParams.hideOptions !== undefined ? {margin: {
                    l: 10,  // left
                    r: 10,  // right
                    t: 40,  // top
                    b: 10   // bottom
                }} : {}),
                title: {text: titles[configValues.metric] + companyName + ' - ' + prettyMonthName(configValues.month)}
            }, {})
        }
        else if(configValues.chartType == "bar")
        {
            // Create graph
            createGraph(plotContainerID, [{x: categories, y: catData, type: 'bar'}], 
                {
                    width: this.urlParams.hideOptions !== undefined ? undefined : 800,
                    height: this.urlParams.hideOptions !== undefined ? undefined : 400,
                    autosize: this.urlParams.hideOptions !== undefined,
                    ...(this.urlParams.hideOptions !== undefined ? {margin: {
                        l: 60,  // left
                        r: 10,  // right
                        t: 40,  // top
                        b: 60   // bottom
                    }} : {}),
                    title: {text: titles[configValues.metric] + companyName + ' - ' + prettyMonthName(configValues.month)},
                    xaxis: {
                        title: {text: 'Ticker'},
                        range: [-0.5, Math.min(categories.length, 30) - 0.5]
                    },
                    yaxis: {
                        title: {text: prettyModeNames[configValues.metric] + ' [$/day]'},
                        range: [0, null]
                    }
                }, {})
        }
        else if(configValues.chartType == "pie")
        {
            // Create graph
            createGraph(plotContainerID, [{labels: categories, values: catData, type: 'pie', textinfo: 'label',textposition: 'inside', insidetextorientation: 'none', automargin: false, hovertemplate: '%{label}<br>$%{value:,.3~s}/day<br>%{percent}<extra></extra>'}], 
                {
                    width: this.urlParams.hideOptions !== undefined ? undefined : 800,
                    height: this.urlParams.hideOptions !== undefined ? undefined : 400,
                    autosize: this.urlParams.hideOptions !== undefined,
                    ...(this.urlParams.hideOptions !== undefined ? {margin: {
                        l: 10,  // left
                        r: 10,  // right
                        t: 40,  // top
                        b: 10   // bottom
                    }} : {}),
                    title: {text: titles[configValues.metric] + companyName + ' - ' + prettyMonthName(configValues.month)},
                    xaxis: {
                        title: {text: 'Ticker'},
                        range: [-0.5, Math.min(categories.length, 30) - 0.5]
                    },
                    yaxis: {
                        title: {text: prettyModeNames[configValues.metric] + ' [$/day]'},
                        range: [0, null]
                    }
                }, {})
        }
    }

}

