import {
  IEquipmentSet,
  IItem,
  IItemContainer,
  isMobile,
  ItemContainerType,
  ItemSlotType,
  ItemType,
} from '@rpg-engine/shared';
import React from 'react';
import styled from 'styled-components';
import { IPosition } from '../../types/eventTypes';
import { DraggableContainer } from '../DraggableContainer';
import { ItemSlotDetailsProvider } from '../Item/Inventory/context/ItemSlotDetailsContext';
import { ItemSlotDraggingProvider } from '../Item/Inventory/context/ItemSlotDraggingContext';
import DraggedItem from '../Item/Inventory/DraggedItem';
import { ItemSlot } from '../Item/Inventory/ItemSlot';
import { ItemSlotToolTips } from '../Item/Inventory/ItemSlotTooltips';
import { RPGUIContainerTypes } from '../RPGUI/RPGUIContainer';

export interface IEquipmentSetProps {
  equipmentSet: IEquipmentSet;
  onClose?: () => void;
  onItemClick?: (
    ItemType: ItemType,
    item: IItem,
    itemContainerType: ItemContainerType | null
  ) => void;
  onItemDragStart?: (
    item: IItem,
    slotIndex: number,
    itemContainerType: ItemContainerType | null
  ) => void;
  onItemDragEnd?: (quantity?: number) => void;
  onItemPlaceDrop?: (
    item: IItem | null,
    slotIndex: number,
    itemContainerType: ItemContainerType | null
  ) => void;
  onItemOutsideDrop?: (item: IItem, position: IPosition) => void;
  scale?: number;
  checkIfItemCanBeMoved: () => boolean;
  checkIfItemShouldDragEnd?: () => boolean;
  onMouseOver?: (e: any, slotIndex: number, item: IItem | null) => void;
  onSelected?: (optionId: string) => void;
  initialPosition?: { x: number; y: number };
  type: ItemContainerType | null;
  atlasIMG: any;
  atlasJSON: any;
  onPositionChangeEnd?: (position: IPosition) => void;
  onPositionChangeStart?: (position: IPosition) => void;
}

export const EquipmentSet: React.FC<IEquipmentSetProps> = ({
  equipmentSet,
  onClose,
  onMouseOver,
  onSelected,
  onItemClick,
  atlasIMG,
  atlasJSON,
  onItemDragEnd,
  onItemDragStart,
  onItemPlaceDrop,
  onItemOutsideDrop,
  checkIfItemCanBeMoved,
  checkIfItemShouldDragEnd,
  scale,
  initialPosition,
  onPositionChangeEnd,
  onPositionChangeStart,
}) => {
  const {
    neck,
    leftHand,
    ring,
    head,
    armor,
    legs,
    boot,
    inventory,
    rightHand,
    accessory,
  } = equipmentSet;

  const equipmentData = [
    neck,
    leftHand,
    ring,
    head,
    armor,
    legs,
    boot,
    inventory,
    rightHand,
    accessory,
  ];

  const equipmentMaskSlots = [
    ItemSlotType.Neck,
    ItemSlotType.LeftHand,
    ItemSlotType.Ring,
    ItemSlotType.Head,
    ItemSlotType.Torso,
    ItemSlotType.Legs,
    ItemSlotType.Feet,
    ItemSlotType.Inventory,
    ItemSlotType.RightHand,
    ItemSlotType.Accessory,
  ];

  const onRenderEquipmentSlotRange = (start: number, end: number) => {
    const equipmentRange = equipmentData.slice(start, end);
    const slotMaksRange = equipmentMaskSlots.slice(start, end);

    return equipmentRange.map((data, i) => {
      const item = data as IItem;
      const itemContainer =
        (item && (item.itemContainer as IItemContainer)) ?? null;

      return (
        <ItemSlot
          key={i}
          slotIndex={i}
          item={item}
          itemContainer={itemContainer}
          itemContainerType={ItemContainerType.Equipment}
          slotSpriteMask={slotMaksRange[i]}
          onMouseOver={(event, slotIndex, item) => {
            if (onMouseOver) onMouseOver(event, slotIndex, item);
          }}
          onPointerDown={(itemType, ContainerType) => {
            if (onItemClick) onItemClick(itemType, item, ContainerType);
          }}
          onDragStart={(item, slotIndex, itemContainerType) => {
            if (!item) {
              return;
            }

            if (onItemDragStart)
              onItemDragStart(item, slotIndex, itemContainerType);
          }}
          onDragEnd={quantity => {
            if (onItemDragEnd) onItemDragEnd(quantity);
          }}
          dragScale={scale}
          checkIfItemCanBeMoved={checkIfItemCanBeMoved}
          checkIfItemShouldDragEnd={checkIfItemShouldDragEnd}
          onPlaceDrop={(item, slotIndex, itemContainerType) => {
            if (onItemPlaceDrop)
              onItemPlaceDrop(item, slotIndex, itemContainerType);
          }}
          onOutsideDrop={(item, position) => {
            if (onItemOutsideDrop) onItemOutsideDrop(item, position);
          }}
          atlasIMG={atlasIMG}
          atlasJSON={atlasJSON}
        />
      );
    });
  };

  return (
    <ItemSlotDraggingProvider>
      <ItemSlotDetailsProvider>
        <DraggedItem atlasIMG={atlasIMG} atlasJSON={atlasJSON} scale={scale} />
        <DraggableContainer
          title={'Equipments'}
          type={RPGUIContainerTypes.Framed}
          onCloseButton={() => {
            if (onClose) onClose();
          }}
          width="330px"
          cancelDrag=".equipment-container-body"
          scale={scale}
          initialPosition={initialPosition}
          onPositionChangeEnd={onPositionChangeEnd}
          onPositionChangeStart={onPositionChangeStart}
        >
          <EquipmentSetContainer className="equipment-container-body">
            <EquipmentColumn>
              {onRenderEquipmentSlotRange(0, 3)}
            </EquipmentColumn>
            <EquipmentColumn>
              {onRenderEquipmentSlotRange(3, 7)}
            </EquipmentColumn>
            <EquipmentColumn>
              {onRenderEquipmentSlotRange(7, 10)}
            </EquipmentColumn>
          </EquipmentSetContainer>
        </DraggableContainer>

        <ItemSlotToolTips
          dragScale={scale}
          atlasIMG={atlasIMG}
          atlasJSON={atlasJSON}
          equipmentSet={equipmentSet}
          onSelected={onSelected}
          isContextMenuDisabled={isMobile()}
        />
      </ItemSlotDetailsProvider>
    </ItemSlotDraggingProvider>
  );
};

const EquipmentSetContainer = styled.div`
  width: inherit;
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  flex-direction: row;
  touch-action: none;
  overflow: hidden;
`;

const EquipmentColumn = styled.div`
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  flex-direction: column;
  touch-action: none;
`;
