import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AgChartInstance,
  AgChartOptions,
  AgPolarChartOptions,
} from "ag-charts-enterprise";
import { getData, random } from "./data";
import "ag-charts-enterprise";
import clone from "clone";

// Series type data options
let start = [120, 150, 130, 140, 80];
let variance = 20;
let offset = 0;
let length = 8;
let seed = 1234;
const barOptions: AgCartesianChartOptions = {
  series: [
    {
      type: "bar",
      xKey: "year",
      yKey: "one",
      yName: "One",
      stacked: true,
    },
    {
      type: "bar",
      xKey: "year",
      yKey: "two",
      yName: "Two",
      stacked: true,
    },
    {
      type: "bar",
      xKey: "year",
      yKey: "three",
      yName: "Three",
      stacked: true,
    },
    {
      type: "bar",
      xKey: "year",
      yKey: "four",
      yName: "Four",
      stacked: true,
    },
    {
      type: "bar",
      xKey: "year",
      yKey: "five",
      yName: "Five",
      stacked: true,
    },
  ],
  axes: [
    {
      type: "number",
      position: "left",
    },
    {
      type: "category",
      position: "bottom",
      label: {
        autoRotate: false,
      },
    },
  ],
};
const lineOptions: AgCartesianChartOptions = {
  series: [
    {
      type: "line",
      xKey: "year",
      yKey: "one",
      yName: "One",
    },
    {
      type: "line",
      xKey: "year",
      yKey: "two",
      yName: "Two",
    },
    {
      type: "line",
      xKey: "year",
      yKey: "three",
      yName: "Three",
    },
    {
      type: "line",
      xKey: "year",
      yKey: "four",
      yName: "Four",
    },
    {
      type: "line",
      xKey: "year",
      yKey: "five",
      yName: "Five",
    },
  ],
  axes: [
    {
      type: "number",
      position: "left",
    },
    {
      type: "number",
      position: "bottom",
      nice: false,
      label: {
        autoRotate: false,
      },
    },
  ],
};
const areaOptions: AgCartesianChartOptions = {
  series: [
    {
      type: "area",
      xKey: "year",
      yKey: "one",
      yName: "One",
      stacked: true,
    },
    {
      type: "area",
      xKey: "year",
      yKey: "two",
      yName: "Two",
      stacked: true,
    },
    {
      type: "area",
      xKey: "year",
      yKey: "three",
      yName: "Three",
      stacked: true,
    },
    {
      type: "area",
      xKey: "year",
      yKey: "four",
      yName: "Four",
      stacked: true,
    },
    {
      type: "area",
      xKey: "year",
      yKey: "five",
      yName: "Five",
      stacked: true,
    },
  ],
  axes: [
    {
      type: "number",
      position: "left",
    },
    {
      type: "number",
      position: "bottom",
      nice: false,
      label: {
        autoRotate: false,
      },
    },
  ],
};
const donutOptions: AgPolarChartOptions = {
  series: [
    {
      type: "pie",
      title: {
        text: "One",
      },
      calloutLabelKey: "year",
      legendItemKey: "year",
      angleKey: "one",
      outerRadiusRatio: 0.6,
    },
    {
      type: "donut",
      title: {
        text: "Two",
      },
      calloutLabelKey: "year",
      legendItemKey: "year",
      angleKey: "two",
      showInLegend: false,
    },
  ],
  axes: [],
};
// Elements
const tickingButton = document.getElementsByClassName(
  "animation-data-updates__toggle-ticking",
)[0];
const actionButtons = document.getElementsByClassName(
  "animation-data-updates__action",
);
function getGeneratedData() {
  return getData(start, variance, offset, length, seed);
}

const ChartExample = () => {
  const [options, setOptions] = useState<
    AgCartesianChartOptions | AgPolarChartOptions
  >({
    animation: {
      enabled: true,
    },
    data: getGeneratedData(),
    ...barOptions,
  });

  const changeSeriesBar = () => {
    const nextOptions = clone(options);

    variance = 20;
    offset = 0;
    length = 8;
    seed = 1234;
    nextOptions.series = barOptions.series;
    nextOptions.axes = barOptions.axes;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const changeSeriesLine = () => {
    const nextOptions = clone(options);

    variance = 4;
    offset = 0;
    length = 30;
    seed = 1234;
    nextOptions.series = lineOptions.series;
    nextOptions.axes = lineOptions.axes;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const changeSeriesArea = () => {
    const nextOptions = clone(options);

    variance = 20;
    offset = 0;
    length = 30;
    seed = 1234;
    nextOptions.series = areaOptions.series;
    nextOptions.axes = areaOptions.axes;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const changeSeriesDonut = () => {
    const nextOptions = clone(options);

    variance = 30;
    offset = 0;
    length = 6;
    seed = 1234;
    nextOptions.series = donutOptions.series;
    nextOptions.axes = donutOptions.axes;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const add = () => {
    const nextOptions = clone(options);

    offset++;
    length++;
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const remove = () => {
    const nextOptions = clone(options);

    if (nextOptions.series?.[0].type === "pie") offset--;
    length = Math.max(0, length - 1);
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const update = () => {
    const nextOptions = clone(options);

    seed = Math.floor(random() * 1000);
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  const addRemoveUpdate = () => {
    const nextOptions = clone(options);

    if (nextOptions.series?.[0].type === "pie") offset--;
    if (nextOptions.series?.[0].type !== "pie") offset++;
    seed = Math.floor(random() * 1000);
    nextOptions.data = getGeneratedData();

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="toolbar">
        <button onClick={changeSeriesBar}>Bar</button>
        <button onClick={changeSeriesLine}>Line</button>
        <button onClick={changeSeriesArea}>Area</button>
        <button onClick={changeSeriesDonut}>Pie &amp; Donut</button>
        <hr />
        <button className="animation-data-updates__action" onClick={add}>
          Add
        </button>
        <button className="animation-data-updates__action" onClick={remove}>
          Remove
        </button>
        <button className="animation-data-updates__action" onClick={update}>
          Update
        </button>
        <hr />
        <button
          className="animation-data-updates__action"
          onClick={addRemoveUpdate}
        >
          Add &amp; Remove &amp; Update
        </button>
      </div>
      <AgCharts options={options as any} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);

/** DARK MODE START **/
import { AgCharts as __chartAPI } from "ag-charts-community";

let darkmode =
  (localStorage["documentation:darkmode"] ||
    String(matchMedia("(prefers-color-scheme: dark)").matches)) === "true";

const isAgThemeOrUndefined = (theme) => {
  return (
    theme == null || (typeof theme === "string" && theme.startsWith("ag-"))
  );
};

const getDarkmodeTheme = (theme = "ag-default", preset) => {
  const baseTheme =
    preset === "price-volume" ? "ag-financial" : theme.replace(/-dark$/, "");
  return darkmode ? baseTheme + "-dark" : baseTheme;
};

__chartAPI.optionsMutationFn = function update(options, preset) {
  const nextOptions = { ...options };
  const theme = options.theme;
  if (isAgThemeOrUndefined(theme)) {
    nextOptions.theme = getDarkmodeTheme(theme, preset);
  } else if (
    typeof theme === "object" &&
    isAgThemeOrUndefined(theme.baseTheme)
  ) {
    nextOptions.theme = {
      ...options.theme,
      baseTheme: getDarkmodeTheme(theme.baseTheme, preset),
    };
  }
  return nextOptions;
};

const applyDarkmode = () => {
  document.documentElement.setAttribute("data-dark-mode", darkmode);
  const charts = document.querySelectorAll("[data-ag-charts]");
  charts.forEach((element) => {
    const chart = __chartAPI.getInstance(element.parentElement);
    if (chart == null) return;
    // This is just needed to trigger the theme update
    chart.update(chart.getOptions());
  });
  return charts.length !== 0;
};

if (!applyDarkmode()) {
  /* React defers updates. Rather than try and hook into the API, just wait until the darkmode is applied. */
  const observer = new MutationObserver(() => {
    if (applyDarkmode()) {
      observer.disconnect();
    }
  });
  observer.observe(document.body, {
    attributes: true,
    childList: true,
    subtree: true,
  });
}
window.addEventListener("message", (event) => {
  if (event.data && event.data.type === "color-scheme-change") {
    darkmode = event.data.darkmode;
    applyDarkmode();
  }
});
/** DARK MODE END **/
