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

export class CompanyRank implements Graph {
    id = "compRank";
    displayName = "Company Rank";
    configFieldIDs = ["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", "month", "Month: ", {prettyValues: monthsPretty, "values": months}, useURLParams && this.urlParams.month ? this.urlParams.month : months[months.length - 1], updateFunc));
        configDiv?.appendChild(addConfigField("input", "companyName", "Username: ", undefined, useURLParams ? this.urlParams.companyName : undefined, updateFunc, "-27px"));
        
    }

    async generatePlot(configValues: any, plotContainerID: string)
    {
        if(!configValues.companyName || configValues.companyName == ""){return;}

        // Get Company Data
        const knownCompanies = await getData(this.loadedData, "knownCompanies");

        // Get Company ID
        var companyID = await getCompanyId(configValues.companyName, this.loadedData) as string;
        
        if(!companyID){ return; }
        var companyName = knownCompanies[companyID]?.Username;

        const fullCompanyData: FullCompanyData = await getData(this.loadedData, "company", configValues.month);
        const fullPrevCompanyData: FullCompanyData = configValues.month == months[0] ?
                {individual: {}} :
                await getData(this.loadedData, "company", months[months.indexOf(configValues.month) - 1]);
        
        const companyData = fullCompanyData.individual[companyID];  // Company data for this company for this month
        const prevCompanyData = fullPrevCompanyData.individual[companyID];  // Company data for this company for last month. May be undefined.
        
        if(!companyData){return;}

        var tableData = [] as any[];   // Entries in the table in raw data form
        var tableDisplay = [] as any[];    // Entries in the table in presentable form

        Object.keys(companyData).forEach(ticker => {
            const tableRow = [companyData[ticker].rank, ticker, companyData[ticker].amount, companyData[ticker].volume, companyData[ticker].profit];
            const tableDisplayRow = [] as any[];

            // Add company rank
            if(prevCompanyData)
            {
                const outerRankDiv = document.createElement("div");
                const symbolDiv = document.createElement("div");
                const rankDiv = document.createElement("div");
                
                outerRankDiv.style.display = "flex";

                symbolDiv.style.width = "14px";
                symbolDiv.style.minWidth = "14px";
                symbolDiv.style.marginRight = "2px";

                const prevRank = prevCompanyData[ticker]?.rank;
                const increasing = prevRank < companyData[ticker].rank;

                if(prevRank && prevRank != companyData[ticker].rank)
                {
                    symbolDiv.textContent = increasing ? "▼" : "▲";
				    symbolDiv.style.color = increasing ? "#d9534f" : "#5cb85c";
                }
                
                rankDiv.textContent = companyData[ticker].rank.toLocaleString();

                outerRankDiv.appendChild(symbolDiv);
                outerRankDiv.appendChild(rankDiv);
                tableDisplayRow.push(outerRankDiv);
            }
            else
            {
                const rankDiv = document.createElement("div");
                rankDiv.textContent = companyData[ticker].rank.toLocaleString();
                tableDisplayRow.push(rankDiv);
            }

            // Add ticker
            const tickerDiv = document.createElement("div");
            tickerDiv.textContent = ticker;
            tableDisplayRow.push(tickerDiv);

            // Add amount
            const amountDiv = document.createElement("div");
            amountDiv.textContent = companyData[ticker].amount.toLocaleString(undefined, {maximumFractionDigits: 1});
            tableDisplayRow.push(amountDiv);

            // Add volume
            const volumeDiv = document.createElement("div");
            volumeDiv.textContent = "$" + companyData[ticker].volume.toLocaleString(undefined, {notation: "compact", maximumSignificantDigits: 3});
            tableDisplayRow.push(volumeDiv);

            // Add profit
            const profitDiv = document.createElement("div");
            const profit = companyData[ticker].profit ?? NaN;
            let profitText: string = "";
            if (profit < 0)
                profitText = "-$" + (-profit).toLocaleString(undefined, {notation: "compact", maximumSignificantDigits: 3});
            else if (profit > 0)
                profitText = "$" + profit.toLocaleString(undefined, {notation: "compact", maximumSignificantDigits: 3});
            profitDiv.textContent = profitText;
            tableDisplayRow.push(profitDiv);

            tableData.push(tableRow);
            tableDisplay.push(tableDisplayRow);
        });

        // Sort by rank by default
        const indices = tableData.map((_, i) => i)
            .sort((a, b) => tableData[a][0] - tableData[b][0]);

        tableData = indices.map(i => tableData[i]);
        tableDisplay = indices.map(i => tableDisplay[i]);

        // Get overall ranks for the title
        const title = "Production Ranking of " + companyName + " - " + prettyMonthName(configValues.month) + "\nVolume: #" + fullCompanyData.totals[companyID].volumeRank + ", Profit: #" + fullCompanyData.totals[companyID].profitRank;

        const headers = ["Rank", "Ticker", "Amount [/day]", "Volume [$/day]", "Profit [$/day]"];
        createTable(plotContainerID, title, headers, tableData, tableDisplay);
    }
}

interface FullCompanyData {
    totals: Record<string, CompanyTotals>;
    individual: Record<string, Record<string, CompanyTickerData>>;
}
interface CompanyTotals {
	volume: number;
	volumeRank: number;
    profitRank?: number;
}
interface CompanyTickerData {
	amount: number;
	volume: number;
	rank: number;
	profit?: number;
}
