import { ProjectState, Selection, CommandSettings } from '../../types';
import siteOrigin from '../../utils/siteOrigin';
import { fromSendable, toSendable } from '../utils/sandboxTools';

const sandbox = document.getElementById('sandbox') as HTMLIFrameElement | null;
if (!sandbox) {
  throw new Error('Sandbox not found.')
}
const sandboxUrl = sandbox.src;

let commandCounter = 0;

const refreshSandbox = () => new Promise<void>((resolve, reject) => {
  const onLoad = () => {
    sandbox.removeEventListener('load', onLoad);
    resolve();
  }
  sandbox.addEventListener('load', onLoad);
  sandbox.src = sandboxUrl;
});

export default <T>(code: string, projectState: ProjectState, selection: Selection, settings: T, isTest: boolean = false): Promise<[ProjectState, Selection, CommandSettings<any>]> => {
  return new Promise(
    async (resolve) => {
      await refreshSandbox();
      commandCounter ++;
      const commandId = `wavtool-command-${commandCounter}`;
      const contentWindow = sandbox.contentWindow
      if (!contentWindow) {
        sandbox.src = sandboxUrl;
        return;
      }

      const handleMessage = (e: MessageEvent) => {
        if (e.data.event === `${commandId}-result`) {
          window.removeEventListener('message', handleMessage);
          resolve([fromSendable(e.data.projectState), e.data.selection, e.data.discoveredSettings]);
        }
      };

      window.addEventListener('message', handleMessage);

      contentWindow.postMessage(
        {
          event: commandId,
          projectState: toSendable(projectState),
          selection,
          settings,
          code,
          isTest
        },
        siteOrigin
      );
    }
  );
}
