/*
 * QQQ - Low-code Application Framework for Engineers.
 * Copyright (C) 2021-2022.  Kingsrook, LLC
 * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
 * contact@kingsrook.com
 * https://github.com/Kingsrook/
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

import Box from "@mui/material/Box";
import React, {ReactNode, useMemo} from "react";
import {Line} from "react-chartjs-2";
import colors from "qqq/assets/theme/base/colors";
import MDBadgeDot from "qqq/components/legacy/MDBadgeDot";

//////////////////////////////////////////
// structure of default line chart data //
//////////////////////////////////////////
export interface DefaultLineChartData
{
   labels: string[];
   lineLabels?: string[];
   datasets: {
      label: string;
      color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
      data: number[];
   }[];
};

/////////////////////
// display options //
/////////////////////
const options = {
   responsive: true,
   maintainAspectRatio: false,
   plugins: {
      legend: {
         display: false,
      },
      tooltip: {
         enabled: true,
         callbacks: {
            label: function(context:any)
            {
               return(" " + Number(context.parsed.y).toLocaleString());
            }
         }
      }
   },
   interaction: {
      intersect: false,
      mode: "index",
   },
   scales: {
      y: {
         beginAtZero: true,
         grid: {
            drawBorder: false,
            display: true,
            drawOnChartArea: true,
            drawTicks: false,
            borderDash: [5, 5],
            color: "#c1c4ce5c",
         },
         ticks: {
            display: true,
            padding: 10,
            color: "#9ca2b7",
            font: {
               size: 14,
               weight: 300,
               family: "Roboto",
               style: "normal",
               lineHeight: 2,
            },
            callback: function(value: any, index: any, values: any)
            {
               return value.toLocaleString();
            }
         },
      },
      x: {
         grid: {
            drawBorder: false,
            display: true,
            drawOnChartArea: true,
            drawTicks: true,
            borderDash: [5, 5],
            color: "#c1c4ce5c",
         },
         ticks: {
            display: true,
            color: "#9ca2b7",
            padding: 10,
            font: {
               size: 14,
               weight: 300,
               family: "Roboto",
               style: "normal",
               lineHeight: 2,
            },
         },
      },
   },
};

/////////////////////////
// inputs and defaults //
/////////////////////////
interface Props
{
   icon?: {
      color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark";
      component: ReactNode;
   };
   height?: string | number;
   description?: any;
   isYAxisCurrency?: boolean;
   data: DefaultLineChartData;

   [key: string]: any;
}

DefaultLineChart.defaultProps = {
   icon: {color: "info", component: ""},
   height: "19.125rem",
};


function DefaultLineChart({data, height, isYAxisCurrency}: Props): JSX.Element
{
   const allBackgroundColors = ["info", "warning", "primary", "success", "error", "secondary", "dark"];
   if (data && data.datasets)
   {
      data.datasets.forEach((ds, index) =>
      {
         // @ts-ignore
         ds.color = allBackgroundColors[index];
      });
   }

   const description= (
      <Box display="flex" justifyContent="space-between">
         <Box display="flex" ml={-1}>
            {
               data?.datasets?.map((dataSet: any) => (
                  <MDBadgeDot key={dataSet.label} color={dataSet.color} size="sm" badgeContent={dataSet.label} />
               ))
            }
         </Box>
         <Box mt={-4} mr={-1} position="absolute" right="1.5rem" />
      </Box>
   );

   const chartDatasets = data && data.datasets
      ? data.datasets.map((dataset) => ({
         ...dataset,
         tension: 0,
         pointRadius: 3,
         borderWidth: 4,
         backgroundColor: "transparent",
         fill: true,
         pointBackgroundColor: colors[dataset.color]
            ? colors[dataset.color || "dark"].main
            : colors.dark.main,
         borderColor: colors[dataset.color]
            ? colors[dataset.color || "dark"].main
            : colors.dark.main,
         maxBarThickness: 6,
      }))
      : [];

   let customOptions = options;
   if(isYAxisCurrency)
   {
      customOptions.scales.y.ticks =
         {
            ... customOptions.scales.y.ticks,
            callback: function(value: any, index: any, values: any)
            {
               return value.toLocaleString("en-US", {style: "currency", currency: "USD", minimumFractionDigits: 0});
            }
         }
      customOptions.plugins.tooltip.callbacks =
         {
            ... customOptions.plugins.tooltip.callbacks,
            label: function(context:any)
            {
               return " " + context.parsed.y.toLocaleString("en-US", {style: "currency", currency: "USD", minimumFractionDigits: 2});
            }
         }
   }

   let fullData = {};
   if (data)
   {
      fullData = {
         labels: data.labels,
         datasets: chartDatasets
      };
   }

   return (
      <Box py={2} pr={2} pl={2}>
         {description}
         {useMemo(
            () => (
               <Box height={height}>
                  <Line data={fullData} options={options} />
               </Box>
            ),

            [data, height]
         )}
      </Box>
   );
}

export default DefaultLineChart;
