import Ace = AceAjax;

export type Mode = Ace.TextMode;

export type Annotation = Ace.Annotation;

export type Options = {
  [name: string]: string | number | boolean | null;
};

export interface Editor extends Ace.Editor {
  commands: CommandManager;
}

interface CommandManager extends Ace.CommandManager {
  // Missing in the latest @types/ace.
  removeCommand(name: string): void;
}

export interface Session extends Ace.IEditSession {
  // An extra property used to keep track of error status.
  fidlboltErrorSession: boolean;

  selection: Selection;
  setMode(mode: Mode | string): void;
}

interface Selection extends Ace.Selection {
  // Missing in the latest @types/ace.
  toJSON(): object;
  fromJSON(json: object): void;
}

export interface SavedSession {
  value: string;
  selection: object;
  scrollTop: number;
  scrollLeft: number;
  undoStack: object;
}

const MAX_SAVED_UNDOS = 100;

export function edit(id: string): Editor {
  return window.ace.edit(id) as Editor;
}

export function createEditSession(text: string, mode: Mode): Session {
  return window.ace.createEditSession(text, mode) as Session;
}

export function sessionToJSON(session: Session): SavedSession {
  const undos = (session.getUndoManager() as any).$undoStack;
  return {
    value: session.getValue(),
    selection: session.selection.toJSON(),
    scrollTop: session.getScrollTop(),
    scrollLeft: session.getScrollLeft(),
    undoStack: undos.slice(Math.max(undos.length - MAX_SAVED_UNDOS, 0)),
  };
}

export function sessionFromJSON(json: SavedSession, mode: Mode): Session {
  const session = ace.createEditSession(json.value, mode) as Session;
  session.selection.fromJSON(json.selection);
  session.setScrollTop(json.scrollTop);
  session.setScrollLeft(json.scrollLeft);
  (session.getUndoManager() as any).$undoStack = json.undoStack;
  session.fidlboltErrorSession = false;
  return session;
}
