import { CodeEditor } from '@jupyterlab/codeeditor';
import type * as CodeMirror from 'codemirror';

/**
 * is_* attributes are there only to enforce strict interface type checking
 */
export interface IPosition extends CodeMirror.Position {}

export function is_equal(self: IPosition, other: IPosition): boolean {
  return other && self.line === other.line && self.ch === other.ch;
}

export interface ISourcePosition extends IPosition {
  is_source: true;
}

export interface IEditorPosition extends IPosition {
  is_editor: true;
}

export interface IVirtualPosition extends IPosition {
  is_virtual: true;
}

export interface IRootPosition extends ISourcePosition {
  is_root: true;
}

// TODO: needs heavy unit testing
export function position_at_offset(
  offset: number,
  lines: string[]
): CodeEditor.IPosition {
  let line = 0;
  let column = 0;
  for (let text_line of lines) {
    // each line has a new line symbol which is accounted for in offset!
    if (text_line.length + 1 <= offset) {
      offset -= text_line.length + 1;
      line += 1;
    } else {
      column = offset;
      break;
    }
  }
  return { line, column };
}

export function offset_at_position(
  position: CodeEditor.IPosition,
  lines: string[],
  lines_include_breaks = false
): number {
  let break_increment = lines_include_breaks ? 0 : 1;
  let offset = 0;
  for (let i = 0; i < lines.length; i++) {
    let text_line = lines[i];
    if (position.line > i) {
      offset += text_line.length + break_increment;
    } else {
      offset += position.column;
      break;
    }
  }
  return offset;
}

export class PositionError extends Error {
  // no-op
}
