import { gray125, gray200, gray300, gray400, gray900, lightLine, moss } from '@/styles/colors';
import styled from '@emotion/styled';
import { useCallback, useEffect, useRef, useState } from 'react';

const GridAnimationWrapper = styled.div`
  position: relative;
  background: ${lightLine};
  width: 100%;
  height: 100%;
  min-height: 200px;
`;

const DeviceNodeWrapper = styled.div<{ top?: number; left?: number }>`
  position: absolute;
`;

const nodeHeight = 70;
const JSDeviceWrapper = styled.div<{ width?: number }>`
  height: ${nodeHeight}px;
  width: ${({ width }) => width || 150}px;
  border-radius: 12px;
  border: 1px solid ${gray400};
  background-color: ${gray125};
`;

const DeviceHeader = styled.header`
  position: relative;
  padding: 6px 12px 5px 12px;
  border-bottom: 1px solid ${gray400};
  font-weight: 600;
  border-top-right-radius: 12px;
  border-top-left-radius: 12px;
`;

const DeviceBody = styled.div<{ shade?: boolean }>`
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  background-color: ${({ shade }) => (shade ? gray200 : 'transparent')};
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
  column-gap: 40px;
  > div {
    padding-bottom: 10px;
  }
`;

const ConnectionListWrapper = styled.div<{ leftSide?: boolean }>`
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  align-items: ${({ leftSide }) => (leftSide ? 'flex-start' : 'flex-end')};
  margin-left: -6px;
  margin-right: -6px;
  > div:after {
    ${({ leftSide }) => (leftSide ? 'left: -8rem' : 'right: -8rem')};
  }
`;

const ConnectionDot = styled.div<{ color: string }>`
  width: 10px;
  height: 10px;
  border-radius: 12px;
  border: 1px solid ${({ color }) => color};
  background-color: ${({ color }) => color};
  position: relative;
`;

const ConnectionWrapper = styled.div`
  color: ${gray900};
  position: relative;
  padding: 7px 0;
  display: flex;
  align-items: center;
  > * + * {
    margin-left: 8px;
  }
`;

const Connections = ({ input, children }: { input: boolean; children?: JSX.Element | string }) => {
  return (
    <ConnectionListWrapper leftSide={input}>
      <ConnectionWrapper>
        {input ? (
          <>
            <ConnectionDot color={moss}></ConnectionDot>
            <div>{children}</div>
          </>
        ) : (
          <>
            <div>{children}</div>
            <ConnectionDot color={moss}></ConnectionDot>
          </>
        )}
      </ConnectionWrapper>
    </ConnectionListWrapper>
  );
};

const Node = ({ children, style, width }: { children: string; style?: React.CSSProperties; width?: number }) => {
  return (
    <DeviceNodeWrapper style={style} color={moss}>
      <JSDeviceWrapper width={width}>
        <DeviceHeader style={{ backgroundColor: '#464A41', color: moss }}>{children}</DeviceHeader>
        <DeviceBody>
          <Connections input={true}>In</Connections>
          <Connections input={false}>Out</Connections>
        </DeviceBody>
      </JSDeviceWrapper>
    </DeviceNodeWrapper>
  );
};

const PortalNodeWrapper = styled.div<{ color: string }>`
  color: ${gray900};
  width: 80px;
  position: relative;
  height: ${50}px;
  border: 1px solid ${({ color }) => color};
  background: ${({ color }) => color};
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  height: 30px;
`;

const Portal = ({
  input = false,
  children,
  style,
}: {
  input?: boolean;
  children: string;
  style?: React.CSSProperties;
}) => {
  return (
    <DeviceNodeWrapper style={style}>
      <PortalNodeWrapper color="#464A41">
        {input ? (
          <>
            <ConnectionDot color={moss} style={{ transform: 'translateX(-5px)' }}></ConnectionDot>
            <div style={{ marginRight: 10 }}>{children}</div>
          </>
        ) : (
          <>
            <div style={{ marginLeft: 10 }}>{children}</div>
            <ConnectionDot color={moss} style={{ transform: 'translateX(5px)' }}></ConnectionDot>
          </>
        )}
      </PortalNodeWrapper>
    </DeviceNodeWrapper>
  );
};

const LineCanvas = styled.canvas`
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  height: 100%;
  position: absolute;
  pointer-events: none;
`;

const BREAKPOINT = 1024;
const ChainEditor = () => {
  const lineCanvasRef = useRef<HTMLCanvasElement>(null);
  const [isMobile, setIsMobile] = useState(true);

  const renderLines = useCallback((mobile: boolean) => {
    const canvas = lineCanvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    if (canvas.width !== canvas.parentElement!.clientWidth || canvas.height !== canvas.parentElement!.clientHeight) {
      canvas.width = canvas.parentElement!.clientWidth;
      canvas.height = canvas.parentElement!.clientHeight;
    }

    ctx.lineWidth = 1;
    ctx.strokeStyle = gray300;

    if (mobile) {
      ctx.beginPath();
      ctx.moveTo(20 + 80, 20 + 35);
      ctx.lineTo(canvas.width - 20, 20 + 35);
      ctx.lineTo(canvas.width - 20, 20 + 35 + 40);
      ctx.lineTo(20 + 80, 20 + 35 + 40);
      ctx.lineTo(20 + 80, canvas.height - 20 - 25);
      ctx.lineTo(canvas.width - 100, canvas.height - 20 - 25);
      ctx.stroke();
      ctx.closePath();
    } else {
      ctx.beginPath();
      ctx.moveTo(20 + 80, 20 + 15);
      ctx.lineTo(150, 20 + 15);
      ctx.lineTo(150, canvas.height / 10 + 45);
      ctx.lineTo(400, canvas.height / 10 + 45);
      ctx.lineTo(400, 3 * (canvas.height / 10) - 20);
      ctx.lineTo(150, 3 * (canvas.height / 10) - 20);
      ctx.lineTo(150, 3 * (canvas.height / 10) + 45);
      ctx.lineTo(400, 3 * (canvas.height / 10) + 45);
      ctx.lineTo(400, canvas.height - canvas.height / 10 - 70 - 20);
      ctx.lineTo(50, canvas.height - canvas.height / 10 - 70 - 20);
      ctx.lineTo(50, canvas.height - canvas.height / 10 - 70 + 45);
      ctx.lineTo(450, canvas.height - canvas.height / 10 - 70 + 45);
      ctx.lineTo(450, canvas.height - 20 - 15);
      ctx.lineTo(canvas.width - 100, canvas.height - 20 - 15);
      ctx.stroke();
      ctx.closePath();
    }
  }, []);

  useEffect(() => {
    setIsMobile(window.innerWidth < BREAKPOINT);
    renderLines(window.innerWidth < BREAKPOINT);
    const handleResize = () => {
      setIsMobile(window.innerWidth < BREAKPOINT);
      renderLines(window.innerWidth < BREAKPOINT);
    };
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  if (isMobile) {
    return (
      <GridAnimationWrapper>
        <LineCanvas ref={lineCanvasRef} />
        <Portal style={{ top: 40, left: 20 }}>MIDI</Portal>
        <Node style={{ top: 13, left: 170 }}>Synth</Node>
        <Node style={{ bottom: 18, right: 150 }} width={100}>
          EQ
        </Node>
        <Portal input style={{ bottom: 30, right: 20 }}>
          Out
        </Portal>
      </GridAnimationWrapper>
    );
  }

  return (
    <GridAnimationWrapper>
      <LineCanvas ref={lineCanvasRef} />
      <Portal style={{ top: 20, left: 20 }}>MIDI</Portal>
      <Node style={{ top: '10%', left: 170 }}>Synth 1</Node>
      <Node style={{ top: '30%', left: 170 }}>Synth 2</Node>
      <Node style={{ bottom: '10%', left: 100 }} width={100}>
        Reverb
      </Node>
      <Node style={{ bottom: '10%', right: 150 }} width={100}>
        EQ
      </Node>
      <Portal input style={{ bottom: 20, right: 20 }}>
        Out
      </Portal>
    </GridAnimationWrapper>
  );
};

export default ChainEditor;
