import React from "react";
import { Meta } from "@storybook/react";
import { GanttProps } from "./GanttProps";
import Gantt from "./Gantt";

import {
  GanttWeekView as KendoGanttWeekView,
  GanttMonthView as KendoGanttMonthView,
  GanttDayView as KendoGanttDayView,
  GanttYearView as KendoGanttYearView,
  filterBy as KendoFilterBy,
  orderBy as KendoOrderBy,
  mapTree as KendoMapTree,
  extendDataItem as KendoExtendDataItem,
  GanttTextFilter as KendoGanttTextFilter,
  GanttDateFilter as KendoGanttDateFilter,
  GanttColumnResizeEvent as KendoGanttColumnResizeEvent,
  GanttColumnReorderEvent as KendoGanttColumnReorderEvent,
  GanttDataStateChangeEvent as KendoGanttDataStateChangeEvent,
  GanttExpandChangeEvent as KendoGanttExpandChangeEvent,
} from "@progress/kendo-react-gantt";

import { getter as KendoGetter } from "@progress/kendo-react-common";
import { exampleTaskData, exampleDependencyData } from "./mockData/data";

const ganttStyle = {
  height: 500,
  width: "100%",
};

const taskModelFields = {
  id: "id",
  start: "start",
  end: "end",
  title: "title",
  percentComplete: "percentComplete",
  isRollup: "isRollup",
  isExpanded: "isExpanded",
  isInEdit: "isInEdit",
  children: "children",
};

const dependencyModelFields = {
  id: "id",
  fromId: "fromId",
  toId: "toId",
  type: "type",
};

const getTaskId = KendoGetter(taskModelFields.id);

const columns = [
  { field: taskModelFields.id, title: "ID", width: 70 },
  {
    field: taskModelFields.title,
    title: "Title",
    width: 200,
    expandable: true,
    filter: KendoGanttTextFilter,
  },
  {
    field: taskModelFields.start,
    title: "Start",
    width: 120,
    format: "{0:MM/dd/yyyy}",
    filter: KendoGanttDateFilter,
  },
  {
    field: taskModelFields.end,
    title: "End",
    width: 120,
    format: "{0:MM/dd/yyyy}",
    filter: KendoGanttDateFilter,
  },
];

export default {
  title: "Design System/Gantt",
  component: Gantt,
  tags: ["autodocs"],
  parameters: {
    docs: {
      description: {
        component:
          'The KendoReact Gantt displays hierarchical tasks data in tabular and timeline formats. It comes with a comprehensive set of ready-to-use features covering everything from data binding directives, sorting, filtering, tasks, and dependencies to intuitive display of task timelines, progression, and styling. \n\n```javascript\nimport { Gantt } from "@renault-ui-library"\n```',
      },
    },
  },
  argTypes: {
    dataTestId: {
      control: { type: "text" },
      description: "Specifies the data-test-id attribute for testing purposes.",
    },
    children: {
      control: { type: "text" },
      description:
        "Specify the available view components as children and the Gantt will match the currently selected view and render it.",
    },
    className: {
      control: { type: "text" },
      description: "Sets custom CSS classes to the Gantt DOM element.",
    },
    columnMenu: {
      control: { type: "object" },
      description: "Custom component for the column menu.",
    },
    columnMenuFilter: {
      control: { type: "object" },
      description: "Column menu filter descriptor.",
    },
    columns: {
      control: { type: "object" },
      description: "A collection of GanttColumnProps for creating columns.",
    },
    defaultView: {
      control: { type: "text" },
      description: "Sets the initially selected view.",
    },
    dependencyData: {
      control: { type: "object" },
      description: "Sets the dependency data of the Gantt component.",
    },
    dependencyModelFields: {
      control: { type: "object" },
      description:
        "The names of the model fields from which the Gantt will read its task data.",
    },
    filter: {
      control: { type: "object" },
      description: "The descriptors by which the data is filtered.",
    },
    navigatable: {
      control: { type: "boolean" },
      description:
        "If set to true, the user can use dedicated shortcuts to interact with the Gantt.",
    },
    noRecords: {
      control: { type: "object" },
      description:
        "Component that will be rendered when the data property of the Gantt is empty or undefined.",
    },
    reorderable: {
      control: { type: "boolean" },
      description:
        "If set to true, the user can reorder columns by dragging their header cells.",
    },
    resizable: {
      control: { type: "boolean" },
      description:
        "If set to true, the user can resize columns by dragging the edges of their header cells.",
    },
    row: {
      control: { type: "object" },
      description: "The Gantt row component.",
    },
    rowHeight: {
      control: { type: "number" },
      description:
        "Defines the row height and implements equal heights for all rows.",
    },
    selectable: {
      control: { type: "object" },
      description: "The Gantt selectable settings.",
    },
    sort: {
      control: { type: "object" },
      description: "The descriptors by which the data is sorted.",
    },
    sortable: { control: { type: "object" }, description: "Enables sorting." },
    style: {
      control: { type: "object" },
      description: "Represents the style HTML attribute.",
    },
    taskData: {
      control: { type: "object" },
      description: "Sets the task data of the Gantt component.",
    },
    taskModelFields: {
      control: { type: "object" },
      description:
        "The names of the model fields from which the Gantt will read its task data.",
    },
    timezone: {
      control: { type: "text" },
      description:
        "Specifies the id of the timezone that will be displayed in the Gantt.",
    },
    toolbar: {
      control: { type: "object" },
      description: "Allow configuration of the Gantt toolbar.",
    },
    view: {
      control: { type: "text" },
      description: "Sets the currently selected view.",
    },
    onAddClick: {
      control: { type: "function" },
      description: "Fires when the user clicks on Gantt add button.",
    },
    onColumnMenuFilterChange: {
      control: { type: "function" },
      description:
        "Fires when the user filters the Gantt columns using the column menu.",
    },
    onColumnReorder: {
      control: { type: "function" },
      description: "Fires when the user reorders the Gantt columns.",
    },
    onColumnResize: {
      control: { type: "function" },
      description: "Fires when the user resizes the Gantt columns.",
    },
    onDataStateChange: {
      control: { type: "function" },
      description: "Fires when the user changes the data state of the Gantt.",
    },
    onDependencyCreate: {
      control: { type: "function" },
      description: "Fires when the user creates a new dependency.",
    },
    onExpandChange: {
      control: { type: "function" },
      description: "Fires when the user expands or collapses a task.",
    },
    onFilterChange: {
      control: { type: "function" },
      description: "Fires when the user filters the Gantt data.",
    },
    onHeaderSelectionChange: {
      control: { type: "function" },
      description:
        "Fires when the user changes the selection in the Gantt header.",
    },
    onKeyDown: {
      control: { type: "function" },
      description: "Fires when the user presses a keyboard key.",
    },
    onRowClick: {
      control: { type: "function" },
      description: "Fires when the user clicks a Gantt row.",
    },
    onRowContextMenu: {
      control: { type: "function" },
      description:
        "Fires when the user opens the context menu for a Gantt row.",
    },
    onRowDoubleClick: {
      control: { type: "function" },
      description: "Fires when the user double-clicks a Gantt row.",
    },
    onSelectionChange: {
      control: { type: "function" },
      description: "Fires when the user changes the selection in the Gantt.",
    },
    onSortChange: {
      control: { type: "function" },
      description: "Fires when the user sorts the Gantt data.",
    },
    onTaskClick: {
      control: { type: "function" },
      description: "Fires when the user clicks a Gantt task.",
    },
    onTaskContextMenu: {
      control: { type: "function" },
      description:
        "Fires when the user opens the context menu for a Gantt task.",
    },
    onTaskDoubleClick: {
      control: { type: "function" },
      description: "Fires when the user double-clicks a Gantt task.",
    },
    onTaskRemoveClick: {
      control: { type: "function" },
      description:
        "Fires when the user clicks the remove button for a Gantt task.",
    },
    onViewChange: {
      control: { type: "function" },
      description: "Fires when the user changes the Gantt view.",
    },
  },
} as Meta;

export const Default = (args: GanttProps): JSX.Element => {
  const [taskData] = React.useState(exampleTaskData);
  const [dependencyData] = React.useState(exampleDependencyData);

  const [expandedState, setExpandedState] = React.useState([7, 11, 12, 13]);
  const [columnsState, setColumnsState] = React.useState<Array<any>>(columns);

  const onColumnResize = React.useCallback(
    (event: KendoGanttColumnResizeEvent) =>
      event.end && setColumnsState(event.columns),
    [setColumnsState]
  );

  const onColumnReorder = React.useCallback(
    (event: KendoGanttColumnReorderEvent) => setColumnsState(event.columns),
    [setColumnsState]
  );

  const [dataState, setDataState] = React.useState<any>({
    sort: [{ field: "orderId", dir: "asc" }],
    filter: [],
  });

  const onDataStateChange = React.useCallback(
    (event: KendoGanttDataStateChangeEvent) =>
      setDataState({
        sort: event.dataState.sort,
        filter: event.dataState.filter,
      }),
    [setDataState]
  );

  const onExpandChange = React.useCallback(
    (event: KendoGanttExpandChangeEvent) => {
      const id = getTaskId(event.dataItem);
      const newExpandedState = event.value
        ? expandedState.filter((currentId) => currentId !== id)
        : [...expandedState, id];

      setExpandedState(newExpandedState);
    },
    [expandedState, setExpandedState]
  );

  const processedData = React.useMemo(() => {
    const filteredData = KendoFilterBy(
      taskData,
      dataState.filter,
      taskModelFields.children
    );
    const sortedData = KendoOrderBy(
      filteredData,
      dataState.sort,
      taskModelFields.children
    );

    return KendoMapTree(sortedData, taskModelFields.children, (task) =>
      KendoExtendDataItem(task, taskModelFields.children, {
        [taskModelFields.isExpanded]: expandedState.includes(getTaskId(task)),
      })
    );
  }, [taskData, dataState, expandedState]);

  return (
    <Gantt
      style={ganttStyle}
      taskData={processedData}
      taskModelFields={taskModelFields}
      dependencyData={dependencyData}
      dependencyModelFields={dependencyModelFields}
      columns={columnsState}
      resizable={true}
      reorderable={true}
      sortable={true}
      sort={dataState.sort}
      filter={dataState.filter}
      onColumnResize={onColumnResize}
      onColumnReorder={onColumnReorder}
      onExpandChange={onExpandChange}
      onDataStateChange={onDataStateChange}
    >
      <KendoGanttWeekView />
      <KendoGanttDayView />
      <KendoGanttMonthView />
      <KendoGanttYearView />
    </Gantt>
  );
};
