import { useEffect, useRef, useState } from 'react';
import styles from './Emulator.module.scss';
import { GAME_SYSTEM_CORES, GameSystem, GameSystemCore } from '@/lib/game';
import { useLanguage } from '@/providers/LanguageProvider';
import { useAPI } from '@/providers/APIProvider';

type SendEmulatorMessageInit = {
  message:'init';
  core:GameSystemCore;
  system:GameSystem;
  gameId:string;
  gameName:string;
}

type SendEmulatorMessageVolume = {
  message:'volume';
  volume:number;
};

type SendEmulatorMessage = (
  SendEmulatorMessageInit |
  SendEmulatorMessageVolume
);

type ReceiveEmulatorMessage = (
  { message: 'iframe_loaded' } |
  { message: 'start' } |
  { message: 'ready' } |
  { message: 'save_state' } |
  { message: 'load_state' } |
  { message: 'save', data:string } |
  { message: 'error', error:string }
);

export type EmulatorProps = {
  system:GameSystem;
  gameId:string;
  gameName:string;
};

export const Emulator:React.FC<EmulatorProps> = props => {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [ hasInit, setHasInit ] = useState(false);
  const { t } = useLanguage();
  const [ saving, setSaving ] = useState<boolean>(false);
  const [ savingError, setSavingError ] = useState<string|null>(null);
  const { saveUpdate } = useAPI();

  const send = (msg:SendEmulatorMessage) => {
    iframeRef.current?.contentWindow?.postMessage(msg, '*');
  };

  const save = async (data:string) => {
    if(saving) return;
    if(!data) return;
    setSaving(true);

    try {
      const res = await saveUpdate({
        gameId: props.gameId,
        data
      });
      console.log('res', res);
    } catch(e) {
      console.error(e);
    } finally {
      setSaving(false);
    }
  }

  useEffect(() => {
    if(hasInit) return;
    setHasInit(true);

    window.onmessage = e => {
      if(!e.data) {
        console.error('Invalid message received:', e.data);
        return;
      }
      
      const msg = e.data as ReceiveEmulatorMessage;
      switch(msg.message) {
        case 'iframe_loaded':
          if(hasInit) return;
          send({
            message: 'init',
            core: GAME_SYSTEM_CORES[props.system],
            system: props.system,
            gameId: props.gameId,
            gameName: props.gameName
          });
          break;

        case 'save':
          save(msg.data).catch(console.error);
          break;

        case 'error':
          console.error('Emulator error:', msg.error);

        case 'start':
        case 'ready':
        case 'load_state':
        case 'save_state':
          break;

        default:
          console.error('Invalid message received:', msg);
          break
      }
    };

    window.onbeforeunload = (e: BeforeUnloadEvent) => {
      e.preventDefault();
      return t('emulator.exit_unsaved');
    };


    return () => {
      window.onbeforeunload = null;
    };
  }, [ ]);

  return (
    <div className={styles.emulator}>
      <div className={[
        styles.emulator__box,
        styles[`emulator__box--${props.system}`]
      ].join(' ')} />

      <iframe
        src="/emulator.html"
        className={styles.emulator__iframe}
        ref={iframeRef}
      />
    </div>
  );
}