import * as React from 'react';
import { FixedSizeList as List } from 'react-window';
import { Menu } from '../Menu/Menu';
import { MenuItem } from '../Menu/MenuItem';
import { handleLeftClick, handleRightClick } from './MouseEventHandlers';
import { IPoint } from '../../Interfaces/IPoint';
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
import { SymbolProperties } from '../SymbolProperties/SymbolProperties';

interface ISymbolsSidebarProps {
  SelectedSymbolId: string
  symbols: Map<string, ISymbolModel>
  isOpen: boolean
  isHistoryOpen: boolean
  OnPropertyChange: (key: string, value: string | number | boolean) => void
  SelectSymbol: (symbolId: string) => void
  DeleteSymbol: (containerid: string) => void
}

export const SymbolsSidebar: React.FC<ISymbolsSidebarProps> = (props: ISymbolsSidebarProps): JSX.Element => {
  // States
  const [isContextMenuOpen, setIsContextMenuOpen] = React.useState<boolean>(false);
  const [onClickSymbolId, setOnClickSymbolId] = React.useState<string>('');
  const [contextMenuPosition, setContextMenuPosition] = React.useState<IPoint>({
    x: 0,
    y: 0
  });

  const elementRef = React.useRef<HTMLDivElement>(null);

  // Event listeners
  React.useEffect(() => {
    const onContextMenu = (event: MouseEvent): void => handleRightClick(
      event,
      setIsContextMenuOpen,
      setOnClickSymbolId,
      setContextMenuPosition
    );

    const onLeftClick = (): void => handleLeftClick(
      isContextMenuOpen,
      setIsContextMenuOpen,
      setOnClickSymbolId
    );

    elementRef.current?.addEventListener(
      'contextmenu',
      onContextMenu
    );

    window.addEventListener(
      'click',
      onLeftClick
    );

    return () => {
      elementRef.current?.removeEventListener(
        'contextmenu',
        onContextMenu
      );

      window.removeEventListener(
        'click',
        onLeftClick
      );
    };
  });

  // Render
  let isOpenClasses = '-right-64';
  if (props.isOpen) {
    isOpenClasses = props.isHistoryOpen
      ? 'right-64'
      : 'right-0';
  }

  const containers = [...props.symbols.values()];
  const Row = ({ index, style }: {index: number, style: React.CSSProperties}): JSX.Element => {
    const container = containers[index];
    const key = container.id.toString();
    const text = key;
    const selectedClass: string = props.SelectedSymbolId !== '' &&
        props.SelectedSymbolId === container.id
      ? 'border-l-4 bg-slate-400/60 hover:bg-slate-400'
      : 'bg-slate-300/60 hover:bg-slate-300';

    return (
      <button
        className={
          `w-full border-blue-500 elements-sidebar-row whitespace-pre
          text-left text-sm font-medium transition-all ${selectedClass}`
        }
        id={key}
        key={key}
        style={style}
        onClick={() => props.SelectSymbol(key)}
      >
        { text }
      </button>
    );
  };

  return (
    <div className={`fixed flex flex-col bg-slate-100 text-gray-800 transition-all h-full w-64 overflow-y-auto z-20 ${isOpenClasses}`}>
      <div className='bg-slate-100 font-bold sidebar-title'>
          Elements
      </div>
      <div ref={elementRef} className='h-96 text-gray-800'>
        <List
          className='List divide-y divide-black'
          itemCount={containers.length}
          itemSize={35}
          height={384}
          width={256}
        >
          { Row }
        </List>
      </div>
      <Menu
        className='transition-opacity rounded bg-slate-200 py-1 drop-shadow-xl'
        x={contextMenuPosition.x}
        y={contextMenuPosition.y}
        isOpen={isContextMenuOpen}
      >
        <MenuItem className='contextmenu-item' text='Delete' onClick={() => {
          setIsContextMenuOpen(false);
          props.DeleteSymbol(onClickSymbolId);
        }} />
      </Menu>
      <SymbolProperties
        symbol={props.symbols.get(props.SelectedSymbolId)}
        symbols={props.symbols}
        onChange={props.OnPropertyChange}
      />
    </div>
  );
};
