import { Meta } from "@storybook/react";
import { GridProps } from "./GridProps";
import Grid from "./Grid";

import {
  GridColumn as KendoGridColumn,
  GridExpandChangeEvent as KendoGridExpandChangeEvent,
  GridGroupChangeEvent as KendoGridGroupChangeEvent,
} from "@progress/kendo-react-grid";
import {
  groupBy as KendoGroupBy,
  GroupDescriptor as KendoGroupDescriptor,
  GroupResult as KendoGroupResult,
} from "@progress/kendo-data-query";

import {
  setExpandedState as KendoSetExpandedState,
  setGroupIds as KendoSetGroupIds,
} from "@progress/kendo-react-data-tools";

import products from "./mockData/products.json";
import { Product } from "./types/interfaces";
import React from "react";

const initialGroup: KendoGroupDescriptor[] = [
  { field: "UnitsInStock" },
  { field: "ProductName" },
];

const processWithGroups = (data: Product[], group: KendoGroupDescriptor[]) => {
  const newDataState = KendoGroupBy(data, group);

  KendoSetGroupIds({ data: newDataState, group: group });

  return newDataState;
};

export default {
  title: "Design System/Data Grid/Grouping",
  component: Grid,
  tags: ["autodocs"],
  parameters: {
    docs: {
      description: {
        component:
          'The KendoReact Data Grid enables you to display grouped table data. \n\n```javascript\nimport { Grid } from "@renault-ui-library"\n```',
      },
    },
  },
  argTypes: {
    ariaLabel: {
      control: { type: "text" },
      description: "The accessible label of the Grid.",
    },
    cells: {
      control: { type: "object" },
      description:
        "Sets a set of custom components that the Grid will render instead of the built-in cell.",
    },
    children: {
      control: { type: "text" },
      description: "Determines the children nodes.",
    },
    className: {
      control: { type: "text" },
      description: "Sets a class of the Grid DOM element.",
    },
    columnMenu: {
      control: { type: "object" },
      description:
        "Specifies a React element that will be cloned and rendered inside the column menu of the Grid.",
    },
    columnVirtualization: {
      control: { type: "boolean" },
      description: "Enables virtualization of the columns.",
    },
    data: {
      control: { type: "object" },
      description: "Sets the data of the Grid.",
    },
    dataItemKey: {
      control: { type: "text" },
      description:
        "Sets the Grid row key prop to the value of this field in the dataItem.",
    },
    detail: {
      control: { type: "object" },
      description:
        "Specifies a React element that will be cloned and rendered inside the detail rows of the Grid.",
    },
    detailRowHeight: {
      control: { type: "number" },
      description: "Defines the detail row height.",
    },
    editField: {
      control: { type: "text" },
      description:
        "Specifies the name of the field which will provide a Boolean representation of the edit state.",
    },
    expandField: {
      control: { type: "text" },
      description:
        "Specifies the name of the field which will provide a Boolean representation of the expanded state.",
    },
    filter: {
      control: { type: "object" },
      description: "The descriptor by which the data is filtered.",
    },
    filterable: {
      control: { type: "boolean" },
      description: "Enables the filtering of the columns.",
    },
    filterOperators: {
      control: { type: "object" },
      description: "The filter operators for the Grid filters.",
    },
    fixedScroll: {
      control: { type: "boolean" },
      description:
        "Determines if the scroll position will be updated after data change.",
    },
    group: {
      control: { type: "object" },
      description: "The descriptors by which the data will be grouped.",
    },
    groupable: {
      control: { type: "object" },
      description:
        "Determines if grouping by dragging and dropping the column headers is allowed.",
    },
    id: {
      control: { type: "text" },
      description:
        "Sets the id property of the top div element of the component.",
    },
    lockGroups: {
      control: { type: "boolean" },
      description: "Defines if the group descriptor columns are locked.",
    },
    navigatable: {
      control: { type: "boolean" },
      description:
        "If set to true, the user can use dedicated shortcuts to interact with the Grid.",
    },
    pageable: {
      control: { type: "object" },
      description: "Configures the pager of the Grid.",
    },
    pager: {
      control: { type: "object" },
      description:
        "The pager component that the Grid will render instead of the built-in pager.",
    },
    pageSize: {
      control: { type: "number" },
      description: "Defines the page size used by the Grid pager.",
    },
    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.",
    },
    rowHeight: {
      control: { type: "number" },
      description:
        "Defines the row height and forces an equal height to all rows.",
    },
    scrollable: {
      control: { type: "text" },
      description: "Defines the scroll mode used by the Grid.",
    },
    selectable: {
      control: { type: "object" },
      description: "The Grid selectable settings.",
    },
    selectedField: {
      control: { type: "text" },
      description:
        "The name of the field which will provide a Boolean representation of the selected state of the items.",
    },
    size: {
      control: { type: "text" },
      description: "Determines the size of the Grid.",
    },
    skip: {
      control: { type: "number" },
      description: "Defines the number of records to be skipped by the pager.",
    },
    sort: {
      control: { type: "object" },
      description: "The descriptors by which the data is sorted.",
    },
    sortable: {
      control: { type: "object" },
      description: "Determines if sorting of the columns is allowed.",
    },
    style: {
      control: { type: "object" },
      description: "Sets the style property of the Grid DOM element.",
    },
    take: {
      control: { type: "number" },
      description: "Defines the number of records to be taken by the pager.",
    },
    total: {
      control: { type: "number" },
      description: "Defines the total number of records that are available.",
    },
    cellRender: {
      control: { type: "function" },
      description: "Custom cell render function.",
    },
    filterCellRender: {
      control: { type: "function" },
      description: "Custom filter cell render function.",
    },
    headerCellRender: {
      control: { type: "function" },
      description: "Custom header cell render function.",
    },
    onColumnReorder: {
      action: "columnReordered",
      description: "Event called when a column is reordered.",
    },
    onColumnResize: {
      action: "columnResized",
      description: "Event called when a column is resized.",
    },
    onContextMenu: {
      action: "contextMenuOpened",
      description: "Event called when the context menu is opened.",
    },
    onDataStateChange: {
      action: "dataStateChanged",
      description: "Event called when the data state changes.",
    },
    onExpandChange: {
      action: "expandChanged",
      description: "Event called when an expandable row is toggled.",
    },
    onFilterChange: {
      action: "filterChanged",
      description: "Event called when the filter is changed.",
    },
    onGroupChange: {
      action: "groupChanged",
      description: "Event called when the grouping is changed.",
    },
    onHeaderSelectionChange: {
      action: "headerSelectionChanged",
      description: "Event called when the header selection is changed.",
    },
    onItemChange: {
      action: "itemChanged",
      description: "Event called when an item is changed.",
    },
    onKeyDown: {
      action: "keyDown",
      description: "Event called when a key is pressed down.",
    },
    onNavigationAction: {
      action: "navigationAction",
      description: "Event called when a navigation action occurs.",
    },
    onPageChange: {
      action: "pageChanged",
      description: "Event called when the page is changed.",
    },
    onRowClick: {
      action: "rowClicked",
      description: "Event called when a row is clicked.",
    },
    onRowDoubleClick: {
      action: "rowDoubleClicked",
      description: "Event called when a row is double-clicked.",
    },
    onScroll: {
      action: "scroll",
      description: "Event called when the grid is scrolled.",
    },
    onSelectionChange: {
      action: "selectionChanged",
      description: "Event called when the selection is changed.",
    },
    onSortChange: {
      action: "sortChanged",
      description: "Event called when the sorting is changed.",
    },
    rowRender: {
      control: { type: "function" },
      description: "Custom row render function.",
    },
  },
} as Meta;

export const Default = (args: GridProps): JSX.Element => {
  const [group, setGroup] = React.useState(initialGroup);
  const [resultState, setResultState] = React.useState<
    Product[] | KendoGroupResult[]
  >(processWithGroups(products, initialGroup));
  const [collapsedState, setCollapsedState] = React.useState<string[]>([]);

  const onGroupChange = React.useCallback(
    (event: KendoGridGroupChangeEvent) => {
      const newDataState = processWithGroups(products, event.group);

      setGroup(event.group);
      setResultState(newDataState);
    },
    []
  );

  const onExpandChange = React.useCallback(
    (event: KendoGridExpandChangeEvent) => {
      const item = event.dataItem;

      if (item.groupId) {
        const newCollapsedIds = !event.value
          ? [...collapsedState, item.groupId]
          : collapsedState.filter((groupId) => groupId !== item.groupId);
        setCollapsedState(newCollapsedIds);
      }
    },
    [collapsedState]
  );

  const newData = KendoSetExpandedState({
    data: resultState,
    collapsedIds: collapsedState,
  });

  return (
    <Grid
      style={{ height: "520px" }}
      groupable={true}
      data={newData}
      onGroupChange={onGroupChange}
      group={group}
      onExpandChange={onExpandChange}
      expandField="expanded"
    >
      <KendoGridColumn
        field="ProductID"
        filterable={false}
        title="ID"
        width="50px"
      />
      <KendoGridColumn field="ProductName" title="Product Name" />
      <KendoGridColumn field="UnitPrice" title="Unit Price" filter="numeric" />
      <KendoGridColumn
        field="UnitsInStock"
        title="Units In Stock"
        filter="numeric"
      />
      <KendoGridColumn field="Category.CategoryName" title="Category Name" />
    </Grid>
  );
};
