import "react-grid-layout/css/styles.css";
import "react-resizable/css/styles.css";
import "./DashboardDesigner.scss";

import { WidthProvider, Responsive } from "react-grid-layout";

import React, { createRef } from "react";
import { Button } from "primereact/button";
import _ from "lodash";
import { Ripple } from "primereact/ripple";
import { OverlayPanel } from "primereact/overlaypanel";
import { Dropdown } from "primereact/dropdown";
import { Dialog } from "primereact/dialog";
import NewWidget from "./NewWidget";
import { Calendar } from 'primereact/calendar';

import ColumnChartComponent from "../ChartsComponents/ColumnChartComponent";
import PieChartComponent from "../ChartsComponents/PieChartComponent";
import MixedChartComponent from "../ChartsComponents/MixedChartComponent";
import AreaChartComponent from "../ChartsComponents/AreaChartComponent";
import TimelineChartComponent from "../ChartsComponents/TimelineChartComponent";
import CandleChartComponent from "../ChartsComponents/CandleChartComponent";
import BarChartComponent from "../ChartsComponents/BarChartComponent";
import { WidgetComponent } from "../types/WidgetComponent";
import { Widget } from "../types/widget";

const ResponsiveReactGridLayout = WidthProvider(Responsive);


class DashboardDesigner extends React.Component<any, any> {
  moreButtonToggle;
  widgetButtonToggle;
  addWidgetButtonToggle;

  widgetComponents: WidgetComponent[] = [
    { type: "Bar", component: BarChartComponent },
    { type: "Column", component: ColumnChartComponent },
    { type: "Pie", component: PieChartComponent },
    { type: "Mixed", component: MixedChartComponent },
    { type: "Timeline", component: TimelineChartComponent },
    { type: "Candle", component: CandleChartComponent },
    { type: "Area", component: AreaChartComponent },
  ];

  constructor(props: any) {
    super(props);

    this.moreButtonToggle = createRef<OverlayPanel>();
    this.widgetButtonToggle = createRef<OverlayPanel>();
    this.addWidgetButtonToggle = createRef<OverlayPanel>();

    var savedLayouts = this.getFromStorage("grid-layout");
    var savedWidgets = this.getFromStorage("grid-widgets");

    this.state = {
      layouts: savedLayouts || { lg: [] },
      showMsg: false,
      dateFilter: null,
      displayDialog: false,
      dashboardTitle: "",
      widgets: savedWidgets || [],
    };
  }
  static get layoutGridProps() {
    return {
      rowHeight: 50,
      className: "layout",
      cols: { lg: 12, md: 10, sm: 2, xs: 1, xxs: 1 },
      // compactType: 'vertical',
      useCSSTransforms: true,
    };
  }

  showMsg = false;

  onLayoutChange(layout: any, layouts) {
    this.saveToStorage("grid-layout", layouts);
    this.saveToStorage("grid-widgets", this.state.widgets);
    this.setState({ layouts });
  }

  deletePanel = (i) => {
    let layout = this.state.layouts["lg"];
    var itemIndex = layout.findIndex((d) => d.i === i);
    layout.splice(itemIndex, 1);

    this.setState({
      layouts: { lg: [...layout] },
      widgets: _.reject(this.state.widgets, { i: i }),
    });

    this.SaveGrid();
  };

  addPanel = (newWidget: Widget) => {
    const widgetComponent = widgetComponents.find(
      (wc) => wc.type === newWidget.WidgetType
    );

    const randomIndex = this.getRandomInt(100, 999);
    const newPanel = {
      i: "" + randomIndex,
      x: (this.state.widgets.length * 2) % 12,
      y: Infinity,
      w: 3,
      h: 5,
      minH: 5,
      minW: 3,
    };
    this.state.widgets.push({
      i: "" + randomIndex,
      title: newWidget.WidgetName,
      component: widgetComponent?.component,
      ...newWidget,
    });

    this.setState({
      layouts: { lg: this.state.layouts["lg"].concat(newPanel) },
      widgets: this.state.widgets,
    });
  };
  SaveGrid() {
    this.saveToStorage("grid-layout", this.state.layouts);
    this.saveToStorage("grid-widgets", this.state.widgets);
  }

  hideDialog = () => {};

  reset() {
    window.localStorage.clear();
    window.location.reload();
  }
  setToken() {
    const token = localStorage.getItem("token");
    const newToken = prompt("Token: ", token || "");
    if(newToken && newToken != '')
      localStorage.setItem("token", newToken || "");
  }

  changeTitle(i) {
    let widget = this.state.widgets[i];

    const newTitle = prompt("Title:");

    widget.title = newTitle;
    this.setState(this.state.widgets);

    this.SaveGrid();
  }
  selectedWidget;
  addComponent(componentType) {
    this.toggleDialog();
  }

  onOkButton = (data: any) => {
    this.toggleDialog();
    this.addPanel(data);
  };

  onCancelButton = () => {
    this.toggleDialog();
  };

  saveToStorage = (key, value) => {
    this.setState({
      showMsg: true,
    });
    setTimeout(() => {
      this.setState({ showMsg: false });
    }, 2000);
    window.localStorage.setItem(key, JSON.stringify(value));
  };

  getFromStorage = (key) => {
    const layout: any = window.localStorage.getItem(key);
    return JSON.parse(layout);
  };

  FindWidget(el: any) {
    return this.state.widgets.find((d) => d.i === el.i);
  }

  toggleDialog() {
    this.setState({ displayDialog: !this.state.displayDialog });
  }

  getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  renderNewWidgetDialog() {
    return (
      <Dialog
        header="New Chart"
        visible={this.state.displayDialog}
        onHide={this.toggleDialog.bind(this)}
        breakpoints={{ "850px": "95vw", "600px": "100vw" }}
        style={{ width: "800px" }}
      >
        <NewWidget
          onOkButton={this.onOkButton}
          onCancelButton={this.onCancelButton}
        />
      </Dialog>
    );
  }

  renderPageHeader() {
    return (
      <header className="dashboard-header">
        <div>
          <h1>{this.state.dashboardTitle || "Dashboard"}</h1>
          <Button
            icon="las la-ellipsis-v"
            onClick={(e) => this.moreButtonToggle.current.toggle(e)}
            className="p-button-lg p-button-rounded p-button-text"
          >
            <Ripple />
          </Button>
          <OverlayPanel ref={this.moreButtonToggle} className="buttons-overlay">
            <div className="buttons-list">
              <div onClick={this.setToken}>set token</div>
              <div onClick={this.reset}>reset</div>
            </div>
          </OverlayPanel>
        </div>
        <div>
          <Button label="<< back to dashboards" className="p-button-link" />
          <Dropdown
            value={this.selectedWidget}
            options={WidgetTypes}
            optionValue="Name"
            optionLabel="Name"
            onChange={(e) => this.addComponent(e.value)}
            placeholder="Add Component"
            optionDisabled={(option) => {
              return option?.Disabled;
            }}
            scrollHeight="300px"
          />
        </div>
      </header>
    );
  }

  renderGridWidgetsPlaceholder() {
    return (
      <div className="grid grid--bordered">
        {[...Array(10)].map((e, i) =>
          [...Array(DashboardDesigner.layoutGridProps.cols.lg)].map((e, i) => (
            <div
              style={{
                height: DashboardDesigner.layoutGridProps.rowHeight,
              }}
            ></div>
          ))
        )}
      </div>
    );
  }

  renderLayoutGrid(layout: any) {
    return (
      <ResponsiveReactGridLayout
        {...DashboardDesigner.layoutGridProps}
        layouts={this.state.layouts}
        compactType="vertical"
        onLayoutChange={(layout, layouts) =>
          this.onLayoutChange(layout, layouts)
        }
      >
        {_.map(layout, (el) => this.renderWidgetComponent(el))}
      </ResponsiveReactGridLayout>
    );
  }

  renderWidgetComponent(el: any) {
    const widget = this.FindWidget(el);
    return (
      <div className="panel" key={el.i}>
        <header>
          <h1>{widget?.title || "not set"}</h1>
          <Button
            icon="las la-ellipsis-v"
            onClick={(e) => this.widgetButtonToggle.current.toggle(e)}
            className="p-button-lg p-button-rounded p-button-text"
          />

          <OverlayPanel ref={this.widgetButtonToggle}>
            <div onClick={this.deletePanel.bind(this, el.i)}>Remove </div>
          </OverlayPanel>
        </header>

        <div className="dashboard-widget">
          {React.createElement(
            this.widgetComponents.find((wc) => wc.type === widget.WidgetType)
              ?.component,
            { key: el.i, dateFilter: this.state.dateFilter, widget: widget }
          )}
        </div>
      </div>
    );
  }

  render() {
    return (
      <>
        {this.renderPageHeader()}

        <Calendar
          value={this.state.dateFilter}
          showIcon={true}
          onChange={(e) => this.setState({ dateFilter: e.value })}
          placeholder="filter by date..."
        ></Calendar>

        <div className="grid-container">
          {this.renderGridWidgetsPlaceholder()}
          {this.renderLayoutGrid(this.state.layouts["lg"])}
        </div>

        {this.renderNewWidgetDialog()}
      </>
    );
  }
}

export default DashboardDesigner;



const WidgetTypes = [
  { Name: "Filter", Disabled: true },
  { Name: "Chart", Disabled: false },
  { Name: "Data Table", Disabled: true },
  { Name: "Pivot Table", Disabled: true },
  { Name: "KPI", Disabled: true },
  { Name: "Gauge", Disabled: true },
];
const widgetComponents = [
  { type: "Bar", component: BarChartComponent },
  { type: "Column", component: ColumnChartComponent },
  { type: "Pie", component: PieChartComponent },
  { type: "Mixed", component: MixedChartComponent },
  { type: "Timeline", component: TimelineChartComponent },
  { type: "Candle", component: CandleChartComponent },
  { type: "Area", component: AreaChartComponent },
];