import { TrashIcon } from '@heroicons/react/outline';
import * as React from 'react';
import { FixedSizeList as List } from 'react-window';
import { IGetFeedbackRequest } from '../../dts/dist/Interfaces/IGetFeedbackRequest';
import { MessageType } from '../../Enums/MessageType';
import { IGetFeedbackResponse } from '../../Interfaces/IGetFeedbackResponse';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IMessage } from '../../Interfaces/IMessage';
import { GetCircularReplacerKeepDataStructure } from '../../utils/saveload';

interface IMessagesSidebarProps {
  historyState: IHistoryState
  isOpen: boolean
}

// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
const myWorker = window.Worker && new Worker('workers/message_worker.js');

function UseWorker(
  state: IHistoryState,
  setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>
): void {
  React.useEffect(() => {
    // use webworker for the stringify to avoid freezing
    myWorker.postMessage({
      state,
      url: import.meta.env.VITE_API_GET_FEEDBACK_URL
    });

    return () => {
    };
  }, [state]);

  React.useEffect(() => {
    myWorker.onmessage = (event) => {
      setMessages(event.data as IMessage[]);
    };
  }, [setMessages]);
}

function UseAsync(
  state: IHistoryState,
  setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>
): void {
  React.useEffect(() => {
    const request: IGetFeedbackRequest = {
      ApplicationState: state
    };
    const dataParsed = JSON.stringify(request, GetCircularReplacerKeepDataStructure());
    fetch(import.meta.env.VITE_API_GET_FEEDBACK_URL, {
      method: 'POST',
      headers: new Headers({
        // eslint-disable-next-line @typescript-eslint/naming-convention
        'Content-Type': 'application/json'
      }),
      body: dataParsed
    })
      .then(async(response) =>
        await response.json()
      )
      .then(async(json: IGetFeedbackResponse) => {
        setMessages(json.messages);
      });
  }, [state]);
}

export function MessagesSidebar(props: IMessagesSidebarProps): JSX.Element {
  const [messages, setMessages] = React.useState<IMessage[]>([]);

  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
  if (window.Worker) {
    UseWorker(
      props.historyState,
      setMessages
    );
  } else {
    UseAsync(
      props.historyState,
      setMessages
    );
  }

  function Row({ index, style }: {index: number, style: React.CSSProperties}): JSX.Element {
    const reversedIndex = (messages.length - 1) - index;
    const message = messages[reversedIndex];
    let classType = '';
    switch (message.type) {
      case MessageType.Success:
        classType = 'bg-green-400 hover:bg-green-400/60';
        break;

      case MessageType.Warning:
        classType = 'bg-yellow-400 hover:bg-yellow-400/60';
        break;

      case MessageType.Error:
        classType = 'bg-red-400 hover:bg-red-400/60';
        break;
    }
    return (<p
      key={`m-${reversedIndex}`}
      className={`p-2 ${classType}`}
      style={style}
    >
      {message.text}
    </p>);
  }

  const isOpenClasses = props.isOpen ? 'left-16' : '-left-64';
  return (
    <div className={`fixed z-10 bg-slate-200
      text-gray-700 transition-all h-full w-64
      ${isOpenClasses}`}>
      <div className='bg-slate-100 sidebar-title flex place-content-between'>
        Messages
        <button
          onClick={() => { setMessages([]); }}
          className='h-6'
          aria-label='Clear all messages'
          title='Clear all messages'
        >
          <TrashIcon className='heroicon'></TrashIcon>
        </button>
      </div>
      <List
        className='List md:text-xs font-bold'
        itemCount={messages.length}
        itemSize={65}
        height={window.innerHeight}
        width={256}
      >
        {Row}
      </List>
    </div>
  );
};
