import React, { memo } from "react";
import styled, { css } from "styled-components";
import { useItemActions, useItemInteraction, useWire } from "react-sync-board";
import { opacify } from "color2k";

import { media2Url } from "../mediaLibrary";
import { isItemInsideElement, getItemElement } from "../utils";

const BagWrapper = styled.div`
${({
    width,
    height,
    labelBackgroundColor = "#cccccc33",
}) => css`
    width: ${width}px;
    height: ${height}px;
    position: relative;
    & .bag__label {
      font-size: 1.5em;
      user-select: none;
      background-color: ${opacify(labelBackgroundColor, 1)};
      position: absolute;
      border-radius: 0.5em;
      color: var(--color-darkGrey);
    }

    & .bag__label.left {
      padding: 1em 0em;
      top: 1em;
      left: -1em;
      letter-spacing: -3px;
      writing-mode: vertical-rl;
      text-orientation: upright;
    }

    & .bag__label.top {
      padding: 0em 1em;
      top: -1em;
      left: 1em;
    }
  `}
`;

const BagImage = styled.img`
  transition: opacity 300ms;
  pointer-events: none;
  display: ${({ visible }) => (visible ? 'block' : 'none')};
`;

const ItemCounter = styled.div`
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: ${({ counterSize }) => `${counterSize}px`}
`;

const Bag = ({
    families,
    storedItems = [],
    label,
    width,
    height,
    bagImage = "/bag.png",
    emptyBagImage = "/bag_empty.png",
    labelPosition = "left",
    countersize = 50,
    countervisible = true,
    labelBackgroundColor = "#cccccc33",
    id,
    setState,
}) => {
    const { isMaster } = useWire("board");
    const { register } = useItemInteraction("place");
    const {
        pushItem,
        getItems,
        batchUpdateItems,
        removeItems,
    } = useItemActions();

    const bagRef = React.useRef(null);

    const noFamilies = !Array.isArray(families) || families.length === 0;

    const imageContent = media2Url(bagImage) || "/bag.png";
    const emptyImageContent = media2Url(emptyBagImage) || "/bag_empty.png";
    const size = {};

    if (width) {
        size.width = width;
    }
    if (height) {
        size.height = height;
    }

    const onInsideItem = React.useCallback(
        async (itemIds) => {
            const items = await getItems(itemIds);
            const insideItems = items
                .filter((item) => noFamilies || families.includes(item.groupId))
                .filter(({ id: itemId }) =>
                    // Skip the container itself.
                    itemId !== id &&
                    isItemInsideElement(getItemElement(itemId), bagRef.current)
                )
                .map(({ id }) => id);

            if (!insideItems.length) return;

            const newItems = await getItems(insideItems);
            await removeItems(newItems.map(item => item.id));

            storedItems = newItems.concat(storedItems);

            setState((prevState) => ({
                ...prevState,
                storedItems: storedItems,
            }));
        }, [families, storedItems, id, setState, getItems, removeItems]
    );

    const onExtract = React.useCallback(
        async () => {
            const [bag] = await getItems([id]);

            storedItems = [...storedItems];
            const item = storedItems.shift();

            if (item) {
                setState((prevState) => ({
                    ...prevState,
                    storedItems: storedItems,
                }));

                await pushItem({
                    ...item,
                    x: bag.x + bagRef.current.clientWidth / 3.0,
                    y: bag.y + bagRef.current.clientHeight / 3.0,
                });
            }
        }, [id, bagRef, storedItems, setState, pushItem]
    );

    const extract = (e) => {
        e.stopPropagation();
        onExtract();
    }

    React.useEffect(() => {
        const unregisterList = [];
        unregisterList.push(register(onInsideItem));

        return () => {
            unregisterList.forEach((callback) => callback());
        };
    }, [onInsideItem, register]);

    return (
        <BagWrapper onDoubleClick={extract} ref={bagRef}
            labelBackgroundColor={labelBackgroundColor}
            width={width}
            height={height}
        >
            {countervisible && (<ItemCounter counterSize={countersize} >{storedItems.length}</ItemCounter>)}
            <BagImage
                visible={storedItems.length}
                src={imageContent}
                alt=""
                draggable={false}
                {...size}
            />
            <BagImage
                visible={!storedItems.length}
                src={emptyImageContent}
                alt=""
                draggable={false}
                {...size}
            />
            <div className={`bag__label ${labelPosition}`}>{label}</div>
        </BagWrapper>
    );
};

export default memo(Bag);