import { useState, useEffect, useRef } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

import AreaBlock from './AreaBlock';
import AreaResize from './AreaResize';
import { useSelect } from '@wordpress/data';
import { BlockInstance } from '@wordpress/blocks';
import { ToolbarGroup, ToolbarItem, Button } from '@wordpress/components';
import { BlockControls } from '@wordpress/block-editor';
import { BiteStyleProps } from '../DesignPanel/types';

import GridIcon from 'blockbite-icons/dist/Grid';
import CheckIcon from 'blockbite-icons/dist/Check';

import has from 'lodash/has';

type AreaCanvasProps = {
  flexStyle: BiteStyleProps[];
  className: string;
  clientId: string;
  blocks: any[];
  setAttributes: (attributes: any) => void;
};

const AreaCanvas = ({
  flexStyle,
  className,
  clientId,
  setAttributes,
}: AreaCanvasProps) => {
  const areaCanvasRef = useRef(null);
  const [isEditing, setIsEditing] = useState(false);
  const [isCanvas, setIsCanvas] = useState(false);
  const [activeBlockId, setActiveBlockId] = useState<string | null>(null);
  const [gridSizeX, setGridSizeX] = useState(null);
  const [gridSizeY, setGridSizeY] = useState(null);
  const [gridGapX, setGridGapX] = useState(null);
  const [gridGapY, setGridGapY] = useState(null);

  interface BlockEditorSelector {
    getBlock: (id: string) => BlockInstance | undefined;
  }

  const currentResponsive = useSelect((select) => {
    // @ts-ignore
    return select('biteStore/editor').getDevice();
  }, []);

  // needs to be refactored

  useEffect(() => {
    const gridStyleX = flexStyle.filter(
      (style) => {
        return ['gridcols', 'gridarea'].includes(style.id);
      },
      [activeBlockId, clientId, innerBlocks]
    );
    const gridStyleY = flexStyle.filter((style) => {
      return ['gridrows', 'gridarea'].includes(style.id);
    });
    /*
    const gridGapStyleX = flexStyle.filter((style) => {
      return ['flexgapx'].includes(style.id);
    });
    const gridGapStyleY = flexStyle.filter((style) => {
      return ['flexgapy'].includes(style.id);
    });
    const gridGapStyleAround = flexStyle.filter((style) => {
      return ['flexgapa'].includes(style.id);
    });
    */
    if (has(gridStyleX, '0.value')) {
      setGridSizeX(parseInt(gridStyleX[0].value));
    } else {
      setGridSizeX(1);
    }
    if (has(gridStyleY, '0.value')) {
      setGridSizeY(parseInt(gridStyleY[0].value));
    } else {
      setGridSizeY(1);
    }

    const flexWidth = flexStyle.find((style) => {
      return style.id === 'flexwidth';
    });

    // experimental
    if (flexWidth?.value === 'b_grid-container') {
      // setIsEditing(false);
      setGridSizeX(14);
      setGridSizeY(4);
    }

    if (areaCanvasRef.current) {
      setGapSize();
    }
  }, [className, isEditing]);

  const setGapSize = () => {
    function calcGapSize() {
      if (!areaCanvasRef.current)
        return { rowGapSize: '0', columnGapSize: '0' };

      const styles = window.getComputedStyle(areaCanvasRef.current);
      const rowGap = styles.getPropertyValue('row-gap');
      const columnGap = styles.getPropertyValue('column-gap');
      // remove px from the string
      const rowGapSize = rowGap.replace('px', '');
      const columnGapSize = columnGap.replace('px', '');
      return {
        rowGapSize,
        columnGapSize,
      };
    }

    const { rowGapSize, columnGapSize } = calcGapSize();
    // if NaN try again
    if (isNaN(parseInt(rowGapSize)) || isNaN(parseInt(columnGapSize))) {
      setTimeout(() => {
        setGapSize();
      }, 100);
    } else {
      setGridGapX(parseInt(columnGapSize));
      setGridGapY(parseInt(rowGapSize));
    }
  };

  /**
   * Mapped instance of innerblocks of clientId
   */
  const innerBlocks = useSelect(
    (select) => {
      const blockEditor: BlockEditorSelector = select('core/block-editor');
      const newAreaBlocks = [] as any;
      blockEditor.getBlock(clientId as string)?.innerBlocks.map((block) => {
        const { biteStyle } = block.attributes;
        newAreaBlocks.push({
          clientId: block.clientId,
          biteStyle: biteStyle ? biteStyle : [],
        });
      });
      return newAreaBlocks;
    },
    [clientId, currentResponsive]
  );

  /**
   *
   * Find Area modifiers within biteStyle
   * @param biteStyle
   * @returns AreaProps
   */

  const handleActivate = (id: string) => {
    setActiveBlockId(id);
  };

  /**
   * Deactivate editing mode if other section is selected so the menu can be accessed
   */
  const selectedBlock = useSelect(
    (select: any) => select('core/block-editor').getSelectedBlock(),
    []
  );

  useSelect(() => {
    if (innerBlocks.includes(selectedBlock?.clientId)) {
      return false;
    } else if (clientId === selectedBlock?.clientId) {
      return false;
    } else {
      setIsEditing(false);
    }
  }, [selectedBlock?.clientId]);

  return (
    <>
      <BlockControls group="other">
        <ToolbarGroup>
          <ToolbarItem
            as={Button}
            onClick={() => {
              setIsEditing(!isEditing);
            }}
          >
            {!isEditing ? <GridIcon /> : <CheckIcon />}
          </ToolbarItem>
        </ToolbarGroup>
      </BlockControls>
      {isEditing && (
        <div
          ref={areaCanvasRef}
          className={`blockbite--areacanvas !absolute inset-0 z-[1000] h-full w-full ${className}`}
          onMouseUp={() => setIsCanvas(false)}
          onMouseDown={() => setIsCanvas(true)}
          onMouseLeave={() => setIsCanvas(false)}
        >
          {innerBlocks.map((block: any) => {
            return (
              <AreaBlock
                setActiveBlockId={handleActivate}
                isActive={activeBlockId === block.clientId}
                key={`areablock__${block.clientId}`}
                clientId={block.clientId}
                gridSizeX={gridSizeX}
                gridSizeY={gridSizeY}
                gridGapX={gridGapX}
                gridGapY={gridGapY}
                isCanvas={isCanvas}
                currentResponsive={currentResponsive}
                biteStyle={block.biteStyle}
              />
            );
          })}
          {/* Gridlines Columns */}
          <div
            className={`blockbite--areacanvas pointer-events-none !absolute inset-0 z-[500] h-full w-full !grid-rows-1 ${className}`}
          >
            {[...Array(gridSizeX)].map((_, i) => {
              return (
                <div
                  key={`blockbite-grid-x-${i}`}
                  className="blockbite--areacanvas__guideline !border !border-dashed !border-blue-400"
                ></div>
              );
            })}
          </div>
          {/* Gridlines Rows */}
          <div
            className={`blockbite--areacanvas pointer-events-none !absolute inset-0 z-[499] h-full w-full !grid-cols-1 ${className}`}
          >
            {[...Array(gridSizeY)].map((_, i) => {
              return (
                <div
                  key={`blockbite-grid-y-${i}`}
                  className="blockbite--areacanvas__guideline !border !border-dashed !border-cyan-400"
                ></div>
              );
            })}
          </div>
          <AreaResize
            currentResponsive={currentResponsive}
            flexStyle={flexStyle}
            setAttributes={setAttributes}
          />
        </div>
      )}
    </>
  );
};

export default AreaCanvas;
