import {Annotation, Editors, Options} from './editors';
import {InputMode, OutputMode} from './mode';
import {Timeout, withTimeout} from './util';

// Timeout for POST requests to the server, in milliseconds.
const POST_REQUEST_TIMEOUT = 15000;

// Delay from unhiding the loader to starting its opacity animation, in
// milliseconds. Too short and the CSS transition doesn't get triggered.
const LOADER_OPACITY_1_DELAY = 20;

// Delay from starting the loader fade-out transition to hiding it, in
// milliseconds. This should be at least as long as the CSS .loader transition.
const LOADER_DISPLAY_NONE_DELAY = 300;

// A request sent to the server.
interface Request {
  inputMode: InputMode;
  outputMode: OutputMode;
  options: Options;
  content: string;
}

// A type used to store past inputs. New inputs are checked to avoid sending
// requests to the server when nothing has changed.
type InputMap = Partial<
  Record<
    InputMode,
    Partial<
      Record<
        OutputMode,
        {
          options: string;
          content: string;
        }
      >
    >
  >
>;

// The server sends deployment information with every response. There is no need
// to specify its fields here because we just forward it to Elm.
type Deployment = object;

// Evaluator sends requests to the server to update the output.
export class Evaluator {
  readonly editors: Editors;
  readonly saveFn: VoidFunction;
  readonly loaderElement: HTMLElement;

  refreshDelay: number;
  stopFn?: VoidFunction;
  lastInput: InputMap;
  active?: Omit<Request, 'content'>;
  loaderTimeout?: Timeout;
  deploymentCallback?: (deployment: Deployment) => void;

  constructor(editors: Editors, saveFn: VoidFunction) {
    this.editors = editors;
    this.saveFn = saveFn;
    this.lastInput = {};
    this.active = undefined;
    this.refreshDelay = Infinity;
    this.stopFn = undefined;
    this.loaderElement = document.getElementById('Loader') as HTMLElement;
    this.loaderTimeout = undefined;
    this.deploymentCallback = undefined;
  }

  onDeloymentUpdated(callback: (deployment: Deployment) => void) {
    this.deploymentCallback = callback;
  }

  setActive(inputMode: InputMode, outputMode: OutputMode, options: Options) {
    this.active = {inputMode, outputMode, options};
  }

  setRefreshDelay(delay: number) {
    this.refreshDelay = delay;
  }

  needsRefresh(request: Request) {
    const forOutput =
      this.lastInput[request.inputMode] ??
      (this.lastInput[request.inputMode] = {});
    const last = forOutput[request.outputMode];
    if (
      last != undefined &&
      last.content === request.content &&
      last.options === JSON.stringify(request.options)
    ) {
      return false;
    }
    forOutput[request.outputMode] = {
      content: request.content,
      options: JSON.stringify(request.options),
    };
    return true;
  }

  // Adds event listeners and starts the idle timeout, so that run() gets called
  // on Ctrl+Enter or Cmd+Enter and this.refreshDelay milliseconds after the
  // user types something in the input editor.
  //
  // This can be called again after stop() to restart. Calling start() a second
  // time without first calling stop() has no effect.
  start() {
    if (this.stopFn != undefined) {
      // Already started.
      return;
    }

    let idleTimeout: Timeout;
    const change = () => {
      clearTimeout(idleTimeout);
      idleTimeout = setTimeout(() => this.run(), this.refreshDelay);
    };
    const unload = () => this.saveFn();
    const blur = () => clearTimeout(idleTimeout);
    const keydown = (event: KeyboardEvent) => {
      if ((event.ctrlKey || event.metaKey) && event.key === 'Enter') {
        clearTimeout(idleTimeout);
        this.run();
        event.stopPropagation();
      }
    };

    this.editors.inputEditor.on('change', change);
    window.addEventListener('unload', unload);
    window.addEventListener('blur', blur);
    window.addEventListener(
      'keydown',
      keydown,
      // Use capturing rather than bubbling so that the Ace editor doesn't get
      // the keydown event first.
      true
    );

    this.stopFn = () => {
      clearTimeout(idleTimeout);
      this.editors.inputEditor.removeEventListener('change', change);
      window.removeEventListener('unload', unload);
      window.removeEventListener('blur', blur);
      window.removeEventListener('keydown', keydown, true);
    };
  }

  // Stops evaluating: removes all event listeners and cancels the idle timer.
  stop() {
    if (this.stopFn != undefined) {
      this.stopFn();
      this.stopFn = undefined;
    }
  }

  // Sends a request to the server (if the input has changed) and updates the
  // output, displaying a loading animation in the meantime.
  async run() {
    if (this.active == undefined) {
      return;
    }
    const request = {
      ...this.active,
      content: this.editors.inputEditor.getValue(),
    };
    if (!this.needsRefresh(request)) {
      return;
    }

    this.startLoadingAnimation();
    const finish = (
      content: string,
      anns?: Annotation[],
      deployment?: object,
      error?: string
    ) => {
      if (deployment != undefined && this.deploymentCallback != undefined) {
        this.deploymentCallback(deployment);
      }
      this.editors.setOutput(
        request.inputMode,
        request.outputMode,
        content,
        anns ?? [],
        error
      );
      this.endLoadingAnimation();
    };

    this.saveFn();
    let response;
    try {
      response = await withTimeout(
        POST_REQUEST_TIMEOUT,
        'Timed out waiting for server to respond',
        fetch('/convert', {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify(request),
        })
      );
    } catch (error) {
      finish(error.message, [], undefined, 'Network Error');
      return;
    }
    if (response.ok) {
      const json = await response.json();
      finish(
        json.content,
        json.annotations,
        json.deployment,
        json.ok ? undefined : 'Error'
      );
    } else {
      let msg;
      if (response.headers.get('Content-Type')?.startsWith('text/plain')) {
        msg = await response.text();
      } else {
        msg = `Server responded with HTTP status ${response.status}`;
        if (response.statusText) {
          msg += ' ' + response.statusText;
        }
      }
      finish(msg, [], undefined, 'Server Error');
    }
  }

  startLoadingAnimation() {
    clearTimeout(this.loaderTimeout);
    this.loaderElement.style.display = 'block';
    this.loaderTimeout = setTimeout(() => {
      this.loaderElement.style.opacity = '1';
    }, LOADER_OPACITY_1_DELAY);
  }

  endLoadingAnimation() {
    clearTimeout(this.loaderTimeout);
    this.loaderElement.style.opacity = '0';
    this.loaderTimeout = setTimeout(() => {
      this.loaderElement.style.display = 'none';
    }, LOADER_DISPLAY_NONE_DELAY);
  }
}
