import React, {createRef, useCallback, useEffect, useState} from 'react';
import {PreviewButtonStyle, PreviewStyle} from "./design-preview.style.js";

let startDragPosition = {x: 0, y: 0};

export function DesignPreview({previewOption = {widthDimension: 0}}) {
  const reference = createRef();
  const [active, setActive] = useState(false);
  const [position, setPosition] = useState({x: getInitialXPosition(previewOption), y: 0});
  const [opacity, setOpacity] = useState(85);

  const keyDownHandler = useCallback(
    function (e) {
      if (!active) {
        return;
      }

      const step = e.shiftKey ? 10 : 1;
      if (e.key === 'ArrowUp') {
        updatePosition({y: step * -1}, true)
      } else if (e.key === 'ArrowDown') {
        updatePosition({y: step}, true)
      } else if (e.key === 'ArrowLeft') {
        updatePosition({x: step * -1}, true)
      } else if (e.key === 'ArrowRight') {
        updatePosition({x: step}, true)
      }

    }, [position, active]);

  useEffect(() => {
    document.addEventListener('keydown', keyDownHandler);

    return () => {
      document.removeEventListener('keydown', keyDownHandler)
    }
  }, [keyDownHandler]);

  useEffect(() => {
    updatePosition({x: getInitialXPosition(previewOption), y: 0});

    window.addEventListener('message', responsiveModeChangesHandler);
    return () => window.removeEventListener('message', responsiveModeChangesHandler);
  }, [previewOption.widthDimension]);

  if (!previewOption) {
    return;
  }

  const disabled = !previewOption.url;

  const classNames = [];
  if (!disabled && active) {
    classNames.push('active');
  }

  if (disabled) {
    classNames.push('disabled');
  }

  const handleOpacityChange = (e) => {
    setOpacity(e.target.value);
  }

  return <>
    <PreviewButtonStyle onClick={() => toggle()} className={classNames.join(' ')} disabled={disabled}/>

    {active && !disabled &&
      <>
        <input type="range" value={opacity} min="0" max="100" onChange={handleOpacityChange}/>
        <PreviewStyle onMouseUp={e => stop(e)} style={{opacity: opacity / 100}}>
          <img src={previewOption.url} alt="" ref={reference}
               onMouseDown={e => start(e)}
               draggable={false}
               style={{top: position.y + 'px', left: position.x + 'px'}}
          />
        </PreviewStyle>
      </>
    }
  </>

  //
  // Functions
  //

  function start(e) {
    startDragPosition.x = e.clientX;
    startDragPosition.y = e.clientY;

    document.body.addEventListener('mousemove', handler);
  }

  function stop(e) {
    const target = reference.current;
    updatePosition({x: target.offsetLeft, y: target.offsetTop});

    document.body.removeEventListener('mousemove', handler);
  }

  function handler(e) {
    const target = reference.current;

    if (target) {
      const updatedPosition = {
        x: target.offsetLeft - (startDragPosition.x - e.clientX),
        y: target.offsetTop - (startDragPosition.y - e.clientY),
      };

      target.style.left = updatedPosition.x + 'px';
      target.style.top = updatedPosition.y + 'px';

      startDragPosition.x = e.clientX;
      startDragPosition.y = e.clientY;
    }
  }

  function toggle() {
    setActive(!active);
  }

  function updatePosition({x, y}, relative = false) {
    x = typeof x === 'undefined' ? position.x : relative ? position.x + x : x;
    y = typeof y === 'undefined' ? position.y : relative ? position.y + y : y;

    setPosition({x, y})
  }

  function getInitialXPosition(previewOption) {
    if (!previewOption) {
      return 0;
    }

    // const scrollbarOffset = 7; Looks like browser scrollbar is not included in the width calculation anymore.
    const scrollbarOffset = 0;
    return window.innerWidth / 2 - previewOption.widthDimension / 2 - scrollbarOffset;
  }

  function responsiveModeChangesHandler(e) {
    if (e.data !== 'responsiveUpdate') {
      return;
    }

    if (window.responsiveState.breakpoint === '100%') {
      updatePosition({x: getInitialXPosition(previewOption), y: 0});
    }
  }
}
