import { FC, PropsWithChildren, createContext, useCallback, useContext, useEffect, useState } from 'react';
import { COMMANDS, DATA, LIST, LOAD } from '../constants';

interface IDataContext {
  list?: IList[];
  file?: string;
  isLoading?: boolean;
  refresh?: () => void;
  load?: (path: string) => void;
}

export interface IList {
  name: string;
  // Base64 PNG
  thumb: string;
  pages: number;
}

export const DataContext = createContext<IDataContext>({});

export const useData = () => {
  const { list, file, isLoading, refresh, load } = useContext(DataContext);

  if (list !== undefined && file !== undefined && isLoading !== undefined && refresh && load) {
    return { list, file, isLoading, refresh, load };
  } else {
    throw new Error("Couldn't find context. Is your component inside a DataProvider?");
  }
};

interface IDataContextProps {
  dataListener: ViewListener.ViewListener;
}

const DataContextProvider: FC<PropsWithChildren<IDataContextProps>> = ({ dataListener, children }) => {
  const [list, setList] = useState<IList[]>([]);
  const [file, setFile] = useState('');
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    dataListener.on(DATA, dataCallback);
    setIsLoading(true);
    setTimeout(() => dataListener.call('COMM_BUS_WASM_CALLBACK', COMMANDS, LIST), 1000);

    return () => dataListener?.off(DATA, dataCallback);
  }, []);

  const dataCallback = useCallback((args: string) => {
    try {
      const json = JSON.parse(args);
      switch (json.id) {
        case LIST:
          setList(json.data);
          window.dispatchEvent(new Event('resize'));
          break;
        case LOAD:
          setFile(json.data);
          window.dispatchEvent(new Event('resize'));
          break;
      }
    } catch (e) {
      console.warn(e);
    }
    setIsLoading(false);
  }, []);

  const refresh = () => {
    setIsLoading(true);
    dataListener.call('COMM_BUS_WASM_CALLBACK', COMMANDS, LIST);
  };

  const load = (path: string) => {
    setIsLoading(true);
    dataListener.call('COMM_BUS_WASM_CALLBACK', COMMANDS, JSON.stringify({ cmd: LOAD, file: path }));
  };

  return <DataContext.Provider value={{ list, file, isLoading, refresh, load }}>{children}</DataContext.Provider>;
};

export default DataContextProvider;
