import * as React from 'react';
import { ReactSVGPanZoom, type Tool, TOOL_PAN, type Value, ALIGN_CENTER } from 'react-svg-pan-zoom';
import { Container } from './Elements/Container';
import { SelectorContainer } from './Elements/SelectorContainer/SelectorContainer';
import { MAX_FRAMERATE } from '../../utils/default';
import { SymbolLayer } from './Elements/SymbolLayer';
import { DimensionLayer } from './Elements/DimensionLayer';
import { SelectorSymbol } from './Elements/SelectorSymbol/SelectorSymbol';
import { type IToolbarProps, Toolbar } from './SVGReactPanZoom/ui-toolbar/toolbar';
import { type DrawParams } from '../Viewer/Viewer';

interface ISVGProps {
  className?: string
  viewerWidth: number
  viewerHeight: number
  width: number
  height: number
  drawParams: DrawParams
  selectContainer: (containerId: string) => void
}

export enum SelectorMode {
  Nothing,
  Containers,
  Symbols
}

export const ID = 'svg';

export function SVG(props: ISVGProps): JSX.Element {
  const {
    mainContainer,
    selectorMode,
    selectedContainer,
    selectedSymbol,
    containers,
    symbols
  } = props.drawParams;
  const [tool, setTool] = React.useState<Tool>(TOOL_PAN);
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
  const [value, setValue] = React.useState<Value>({} as Value);
  const [scale, setScale] = React.useState<number>(value.a ?? 1);

  const svgViewer = React.useRef<ReactSVGPanZoom>(null);

  // Framerate limiter
  const delta = React.useRef(0);
  const timer = React.useRef(performance.now());
  const renderCounter = React.useRef(0);
  // Debug: FPS counter
  // const startTimer = React.useRef(Date.now());
  // console.log(renderCounter.current / ((Date.now() - startTimer.current) / 1000));

  UseFitOnce(svgViewer, props.width, props.height);

  const xmlns = '<http://www.w3.org/2000/svg>';
  const properties = {
    width: props.width,
    height: props.height,
    xmlns
  };

  const children: React.ReactNode | React.ReactNode[] = <Container
    key={`container-${mainContainer.properties.id}`}
    containers={containers}
    model={mainContainer}
    depth={0}
    scale={scale}
    selectContainer={props.selectContainer}
  />;

  function Selector(): JSX.Element {
    switch (selectorMode) {
      case SelectorMode.Containers:
        return <SelectorContainer
          containers={containers}
          scale={scale}
          selected={selectedContainer}
        />;
      case SelectorMode.Symbols:
        return <SelectorSymbol
          symbols={symbols}
          selected={selectedSymbol}
        />;
      default:
        return <></>;
    }
  }

  return (
    <div id={ID} className={props.className}>
      <ReactSVGPanZoom
        ref={svgViewer}
        width={props.viewerWidth}
        height={props.viewerHeight}
        tool={tool} onChangeTool={setTool}
        value={value} onChangeValue={(value: Value) => {
          // Framerate limiter
          const newTimer = performance.now();
          delta.current += (newTimer - timer.current) / 1000;
          timer.current = newTimer;
          if (delta.current <= (1 / MAX_FRAMERATE)) {
            return;
          }

          renderCounter.current = renderCounter.current + 1;
          delta.current = delta.current % (1 / MAX_FRAMERATE);
          setValue(value);
        }}
        onZoom={(event: unknown) => {
          const value = event as Value;
          setScale(value.a);
        }}
        onDoubleClick={() => {
          svgViewer?.current?.setPointOnViewerCenter(props.width / 2, props.height / 2, 0.8);
        }}
        background={'#ffffff'}
        defaultTool='pan'
        miniatureProps={{
          position: 'left',
          background: '#616264',
          width: 120,
          height: 120
        }}
        customToolbar={(props: IToolbarProps) => (
          <Toolbar
            {...props}
            SVGAlignX={ALIGN_CENTER}
            SVGAlignY={ALIGN_CENTER}
            fittingScale={0.8}
          />
        )}
      >
        <svg {...properties}>
          {children}
          <DimensionLayer
            containers={containers}
            symbols={symbols}
            scale={scale}
            root={mainContainer}
          />
          <SymbolLayer scale={scale} symbols={symbols} />
          <Selector />
        </svg>
      </ReactSVGPanZoom>
    </div>
  );
}

function UseFitOnce(svgViewer: React.RefObject<ReactSVGPanZoom>, width: number, height: number): void {
  React.useCallback(() => {
    // TODO: Fix this
    svgViewer?.current?.setPointOnViewerCenter(width / 2, height / 2, 0.8);
  }, [svgViewer, width, height]);
}
