import { useEffect, useState, useContext } from '@wordpress/element';

import BorderAll from 'blockbite-icons/dist/BorderAll';
import BorderSplit from 'blockbite-icons/dist/BorderSplit';
import BorderHorizontal from 'blockbite-icons/dist/BorderHorizontal';
import BorderVertical from 'blockbite-icons/dist/BorderVertical';

import MetricsControl from '@components/ui/MetricsControl';
import { DropdownPicker } from '@components/ui/DropdownPicker';

import {
  spaceValuesToOptions,
  optionsToSpaceValues,
} from '@components/DesignPanel/DynamicControls/SpacingHelpers';

import { useActiveOptionValues } from '@components/DesignPanel/hooks/useActiveOptionvalue';
import { useStore } from 'zustand';
import { DesignContext } from '@components/DesignPanel/DesignStore';
import has from 'lodash/has';
import { ModifierPanelProps } from '@components/DesignPanel/types';

export const Spacing: React.FC<ModifierPanelProps> = ({
  currentControlId,
  emitOptions,
}) => {
  const store = useStore(useContext(DesignContext));

  const [values, setValues] = useState({
    top: { value: '', unit: 'arbitrary' },
    right: { value: '', unit: 'arbitrary' },
    bottom: { value: '', unit: 'arbitrary' },
    left: { value: '', unit: 'arbitrary' },
    direction: 'side',
  });

  const [axis, setAxis] = useState<'side' | 'horizontal' | 'vertical' | 'all'>(
    'side'
  );

  const [modifierIds, setModifierIds] = useState<string[]>([]);

  const SideOptions = [
    {
      icon: <BorderSplit />,
      label: 'Side',
      value: 'side',
      onClick: () => setAxis('side'),
    },
    {
      icon: <BorderAll />,
      label: 'All Sides',
      id: 'all',
      value: 'all',
      onClick: () => setAxis('all'),
    },
    {
      icon: <BorderHorizontal />,
      label: 'Horizontal',
      value: 'horizontal',
      onClick: () => setAxis('horizontal'),
    },
    {
      icon: <BorderVertical />,
      label: 'Vertical',
      value: 'vertical',
      onClick: () => setAxis('vertical'),
    },
  ];

  const handleValueChange = (
    side: 'top' | 'right' | 'bottom' | 'left',
    value: string,
    unit: string
  ) => {
    // make sure unit is a string
    const newValue = unit !== undefined ? String(value) : '0';

    switch (axis) {
      case 'horizontal':
        if (side === 'left' || side === 'right') {
          setValues((prevValues) => ({
            ...prevValues,
            left: { value: newValue, unit },
            right: { value: newValue, unit },
            direction: 'horizontal',
          }));
        }
        break;
      case 'vertical':
        if (side === 'top' || side === 'bottom') {
          setValues((prevValues) => ({
            ...prevValues,
            top: { value: newValue, unit },
            bottom: { value: newValue, unit },
            direction: 'vertical',
          }));
        }
        break;
      case 'all':
        setValues({
          top: { value: newValue, unit },
          right: { value: newValue, unit },
          bottom: { value: newValue, unit },
          left: { value: newValue, unit },
          direction: 'all',
        });
        break;
      case 'side':
      default:
        setValues((prevValues) => ({
          ...prevValues,
          [side]: { value: newValue, unit },
          direction: 'side',
        }));
        break;
    }
  };

  const activeOptionValues = useActiveOptionValues(modifierIds, store);

  // set initial values
  useEffect(() => {
    if (has(blockbite.codex.controls, currentControlId)) {
      setModifierIds(blockbite.codex.controls[currentControlId]);
    }

    const options = optionsToSpaceValues(activeOptionValues, currentControlId);

    setValues({ ...options, direction: 'side' });
  }, [activeOptionValues]);

  // update options
  useEffect(() => {
    const options = spaceValuesToOptions(values, currentControlId);

    emitOptions(options);
  }, [values]);

  const handleUnitChange = (
    side: 'top' | 'right' | 'bottom' | 'left',
    unit: string
  ) => {
    handleValueChange(side, values[side].value, unit);
  };

  return (
    <div>
      <div className="grid min-h-[120px] grid-cols-3 grid-rows-3">
        <span className="col-span-1"></span>
        <span className="col-span-1 flex items-center justify-center">
          <MetricsControl
            defaultValue={values.top.value}
            defaultUnit={values.top.unit}
            inputClassName={'w-[50px]'}
            onValueChange={(value) =>
              handleValueChange('top', value, values.top.unit)
            }
            onUnitChange={(unit) => handleUnitChange('top', unit)}
          />
        </span>
        <span className="col-span-1"></span>
        <span className="col-span-1 flex items-center justify-center">
          <MetricsControl
            defaultValue={values.left.value}
            defaultUnit={values.left.unit}
            inputClassName={'w-[50px]'}
            onValueChange={(value) =>
              handleValueChange('left', value, values.left.unit)
            }
            onUnitChange={(unit) => handleUnitChange('left', unit)}
          />
        </span>
        <div className="col-span-1 flex items-center justify-center">
          {currentControlId !== 'transform' && (
            <DropdownPicker
              defaultValue={values.right.unit}
              options={SideOptions}
              onPressedChange={(unit: string) => setAxis(unit as any)}
            />
          )}
        </div>
        <span className="col-span-1 flex items-center justify-center">
          <MetricsControl
            defaultValue={values.right.value}
            defaultUnit={values.right.unit}
            inputClassName={'w-[50px]'}
            onValueChange={(value) =>
              handleValueChange('right', value, values.right.unit)
            }
            onUnitChange={(unit) => handleUnitChange('right', unit)}
          />
        </span>
        <span className="col-span-1"></span>
        <span className="col-span-1 flex items-center justify-center">
          <MetricsControl
            defaultValue={values.bottom.value}
            defaultUnit={values.bottom.unit}
            inputClassName={'w-[50px]'}
            onValueChange={(value) =>
              handleValueChange('bottom', value, values.bottom.unit)
            }
            onUnitChange={(unit) => handleUnitChange('bottom', unit)}
          />
        </span>
        <span className="col-span-1"></span>
      </div>
    </div>
  );
};

export default Spacing;
