import React, { useRef, useState } from "react";
import { Meta } from "@storybook/react";
import { ListBoxProps } from "./ListBoxProps";
import ListBox from "./ListBox";
import {
  ListBoxToolbar,
  processListBoxData,
  ListBoxToolbarClickEvent,
  ListBoxItemClickEvent,
} from "@progress/kendo-react-listbox";

type DataItem = { name: string; selected: boolean };

type State = {
  employees: DataItem[];
  developers: DataItem[];
};

const data: DataItem[] = [
  { name: "Steven White", selected: true },
  { name: "Nancy King", selected: false },
  { name: "Nancy Davolio", selected: false },
  { name: "Robert Davolio", selected: false },
  { name: "Michael Leverling", selected: false },
  { name: "Andrew Callahan", selected: false },
  { name: "Michael Suyama", selected: false },
];

const SELECTED_FIELD = "selected";

export default {
  title: "Design System/ListBox",
  component: ListBox,
  tags: ["autodocs"],
  parameters: {
    docs: {
      description: {
        component:
          'The KendoReact ListBox enables you to display lists of items and to move the items between multiple lists.  \n\n```javascript\nimport { ListBox } from "@renault-ui-library"\n```',
      },
    },
  },
  argTypes: {
    dataTestId: {
      control: { type: "text" },
      description: "Specifies the data-test-id attribute for testing purposes.",
    },
    className: {
      control: { type: "text" },
      description: "Sets a class of the Tooltip animation container.",
    },
    data: {
      control: { type: "array" },
      description: "Set the data of the ListBox.",
    },
    draggable: {
      control: { type: "boolean" },
      description: "Makes the items of the ListBox draggable.",
    },
    item: {
      control: { type: "object" },
      description: "Defines the component that will be rendered for each item.",
    },
    selectedField: {
      control: { type: "text" },
      description: "Set the selected field of the ListBox.",
    },
    size: {
      control: {
        type: "select",
        options: ["null", "small", "medium", "large"],
      },
      description: "Configures the size of the ListBox.",
    },
    style: {
      control: { type: "object" },
      description: "Specifies the styles.",
    },
    textField: {
      control: { type: "text" },
      description: "Sets the data item field that represents the item text.",
    },
    toolbar: {
      control: { type: "object" },
      description: "Renders a toolbar component next to the ListBox.",
    },
    toolbarPosition: {
      control: { type: "text" },
      description: "Sets the position of the toolbar of the ListBox.",
    },
    valueField: {
      control: { type: "text" },
      description: "The field that be used during form submit.",
    },
    onDragLeave: {
      control: { type: "object" },
      description:
        "Fires when a dragged element or text selection leaves the ListBox element.",
    },
    onDragOver: {
      control: { type: "object" },
      description: "Fires when the user drags over an item from the ListBox.",
    },
    onDragStart: {
      control: { type: "object" },
      description:
        "Fires when the user starts to drag an item from the ListBox.",
    },
    onDrop: {
      control: { type: "object" },
      description: "Fires when the user drops an item.",
    },
    onItemClick: {
      control: { type: "object" },
      description: "Fires when an item from the ListBox is clicked.",
    },
    onKeyDown: {
      control: { type: "object" },
      description: "Fires on keydown over the ListBox list items.",
    },
  },
} as Meta;

export const Default = (args: ListBoxProps): JSX.Element => {
  const lastSelectedIndex = useRef<number>(0);
  const [state, setState] = useState<State>({
    employees: data,
    developers: [],
  });

  const handleItemClick = (
    event: ListBoxItemClickEvent,
    data: keyof State,
    connectedData: keyof State
  ) => {
    let last: number = lastSelectedIndex.current;
    const newData = [...state[data]];
    const current = newData.findIndex(
      (dataItem) => dataItem === event.dataItem
    );

    if (!event.nativeEvent.shiftKey) {
      lastSelectedIndex.current = last = current;
    }

    if (!event.nativeEvent.ctrlKey) {
      newData.forEach((item) => (item.selected = false));
    }
    const select = !event.dataItem.selected;
    if (last <= newData.length - 1) {
      for (let i = Math.min(last, current); i <= Math.max(last, current); i++) {
        newData[i].selected = select;
      }
    }
    setState({
      ...state,
      [data]: newData,
      [connectedData]: state[connectedData].map((item: DataItem) => {
        item[SELECTED_FIELD] = false;
        return item;
      }),
    });
  };

  const handleToolBarClick = (e: ListBoxToolbarClickEvent) => {
    let toolName: string = e.toolName || "";
    let result: any = processListBoxData(
      state.employees,
      state.developers,
      toolName,
      SELECTED_FIELD
    );
    setState({
      ...state,
      employees: result.listBoxOneData.map((item: { selected: boolean }) => {
        item.selected = false;
        return item;
      }),
      developers: result.listBoxTwoData.map((item: { selected: boolean }) => {
        item.selected = false;
        return item;
      }),
    });
  };

  return (
    <div style={{ display: "flex", width: "600px", justifyContent: "center" }}>
      <div style={{ width: "100%" }}>
        <h6>Employees</h6>
        <ListBox
          {...args}
          style={{ height: 350, width: "100%" }}
          data={state.employees}
          textField="name"
          selectedField={SELECTED_FIELD}
          onItemClick={(e: ListBoxItemClickEvent) =>
            handleItemClick(e, "employees", "developers")
          }
          toolbar={() => {
            return (
              <ListBoxToolbar
                tools={[
                  "moveUp",
                  "moveDown",
                  "transferTo",
                  "transferFrom",
                  "transferAllTo",
                  "transferAllFrom",
                  "remove",
                ]}
                data={state.employees}
                dataConnected={state.developers}
                onToolClick={handleToolBarClick}
              />
            );
          }}
        />
      </div>
      <div style={{ width: "100%", marginLeft: "12px" }}>
        <h6>Developers</h6>
        <ListBox
          {...args}
          style={{ height: 350, width: "100%" }}
          data={state.developers}
          textField="name"
          selectedField={SELECTED_FIELD}
          onItemClick={(e: ListBoxItemClickEvent) =>
            handleItemClick(e, "developers", "employees")
          }
        />
      </div>
    </div>
  );
};

Default.args = {
  dataTestId: "listbox-data-testid",
  className: "custom-class",
  data: ["Item1", "Item2"],
  draggable: true,
  selectedField: "id",
  size: "medium",
  style: { width: "200px" },
  textField: "name",
  toolbar: null,
  toolbarPosition: "right",
  valueField: "id",
};
