// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


import m from 'mithril';

import {EngineProxy} from '../common/engine';
import {QueryResponse, runQuery} from '../common/queries';

import {addTab} from './bottom_tab';
import {globals} from './globals';
import {createPage} from './pages';
import {QueryHistoryComponent, queryHistoryStorage} from './query_history';
import {QueryResultTab} from './query_result_tab';
import {QueryTable} from './query_table';

const INPUT_PLACEHOLDER = 'Enter query and press Cmd/Ctrl + Enter';
const INPUT_MIN_LINES = 2;
const INPUT_MAX_LINES = 10;
const INPUT_LINE_HEIGHT_EM = 1.2;
const TAB_SPACES = 2;
const TAB_SPACES_STRING = ' '.repeat(TAB_SPACES);

interface AnalyzePageState {
  enteredText: string;
  executedQuery?: string;
  queryResult?: QueryResponse;
}

const state: AnalyzePageState = {
  enteredText: '',
};

export function runAnalyzeQuery(query: string) {
  state.executedQuery = query;
  state.queryResult = undefined;
  const engine = getEngine();
  if (engine) {
    runQuery(query, engine).then((resp: QueryResponse) => {
      addTab({
        kind: QueryResultTab.kind,
        tag: 'analyze_page_query',
        config: {
          query: query,
          title: 'Standalone Query',
          prefetchedResponse: resp,
        },
      });
      // We might have started to execute another query. Ignore it in that case.
      if (state.executedQuery !== query) {
        return;
      }
      state.queryResult = resp;
      globals.rafScheduler.scheduleFullRedraw();
    });
  }
}

function getEngine(): EngineProxy|undefined {
  const engineId = globals.getCurrentEngine()?.id;
  if (engineId === undefined) {
    return undefined;
  }
  const engine = globals.engines.get(engineId)?.getProxy('AnalyzePage');
  return engine;
}

class QueryInput implements m.ClassComponent {
  // How many lines to display if the user hasn't resized the input box.
  displayLines = INPUT_MIN_LINES;

  static onKeyDown(e: Event) {
    const event = e as KeyboardEvent;
    const target = e.target as HTMLTextAreaElement;
    const {selectionStart, selectionEnd} = target;

    if (event.code === 'Enter' && (event.metaKey || event.ctrlKey)) {
      event.preventDefault();
      let query = target.value;
      if (selectionEnd > selectionStart) {
        query = query.substring(selectionStart, selectionEnd);
      }
      if (!query) return;
      queryHistoryStorage.saveQuery(query);

      runAnalyzeQuery(query);
    }

    if (event.code === 'Tab') {
      // Handle tabs to insert spaces.
      event.preventDefault();
      const lastLineBreak = target.value.lastIndexOf('\n', selectionEnd);

      if (selectionStart === selectionEnd || lastLineBreak < selectionStart) {
        // Selection does not contain line breaks, therefore is on a single
        // line. In this case, replace the selection with spaces. Replacement is
        // done via document.execCommand as opposed to direct manipulation of
        // element's value attribute because modifying latter programmatically
        // drops the edit history which breaks undo/redo functionality.
        document.execCommand('insertText', false, TAB_SPACES_STRING);
      } else {
        this.handleMultilineTab(target, event);
      }
    }
  }

  // Handle Tab press when the current selection is multiline: find all the
  // lines intersecting with the selection, and either indent or dedent (if
  // Shift key is held) them.
  private static handleMultilineTab(
      target: HTMLTextAreaElement, event: KeyboardEvent) {
    const {selectionStart, selectionEnd} = target;
    const firstLineBreak = target.value.lastIndexOf('\n', selectionStart - 1);

    // If no line break is found (selection begins at the first line),
    // replacementStart would have the correct value of 0.
    const replacementStart = firstLineBreak + 1;
    const replacement = target.value.substring(replacementStart, selectionEnd)
                            .split('\n')
                            .map((line) => {
                              if (event.shiftKey) {
                                // When Shift is held, remove whitespace at the
                                // beginning
                                return this.dedent(line);
                              } else {
                                return TAB_SPACES_STRING + line;
                              }
                            })
                            .join('\n');
    // Select the range to be replaced.
    target.setSelectionRange(replacementStart, selectionEnd);
    document.execCommand('insertText', false, replacement);
    // Restore the selection to match the previous selection, allowing to chain
    // indent operations by just pressing Tab several times.
    target.setSelectionRange(
        replacementStart, replacementStart + replacement.length);
  }

  // Chop off up to TAB_SPACES leading spaces from a string.
  private static dedent(line: string): string {
    let i = 0;
    while (i < line.length && i < TAB_SPACES && line[i] === ' ') {
      i++;
    }
    return line.substring(i);
  }

  onInput(textareaValue: string) {
    const textareaLines = textareaValue.split('\n').length;
    const clampedNumLines =
        Math.min(Math.max(textareaLines, INPUT_MIN_LINES), INPUT_MAX_LINES);
    this.displayLines = clampedNumLines;
    state.enteredText = textareaValue;
    globals.rafScheduler.scheduleFullRedraw();
  }

  // This method exists because unfortunatley setting custom properties on an
  // element's inline style attribue doesn't seem to work in mithril, even
  // though the docs claim so.
  setHeightBeforeResize(node: HTMLElement) {
    // +2em for some extra breathing space to account for padding.
    const heightEm = this.displayLines * INPUT_LINE_HEIGHT_EM + 2;
    // We set a height based on the number of lines that we want to display by
    // default. If the user resizes the textbox using the resize handle in the
    // bottom-right corner, this height is overridden.
    node.style.setProperty('--height-before-resize', `${heightEm}em`);
    // TODO(dproy): The resized height is lost if user navigates away from the
    // page and comes back.
  }

  oncreate(vnode: m.VnodeDOM) {
    // This makes sure query persists if user navigates to other pages and comes
    // back to analyze page.
    const existingQuery = state.enteredText;
    const textarea = vnode.dom as HTMLTextAreaElement;
    if (existingQuery) {
      textarea.value = existingQuery;
      this.onInput(existingQuery);
    }

    this.setHeightBeforeResize(textarea);
  }

  onupdate(vnode: m.VnodeDOM) {
    this.setHeightBeforeResize(vnode.dom as HTMLElement);
  }

  view() {
    return m('textarea.query-input', {
      placeholder: INPUT_PLACEHOLDER,
      onkeydown: (e: Event) => QueryInput.onKeyDown(e),
      oninput: (e: Event) =>
          this.onInput((e.target as HTMLTextAreaElement).value),
    });
  }
}


export const AnalyzePage = createPage({
  view() {
    return m(
        '.analyze-page',
        m(QueryInput),
        state.executedQuery === undefined ? null : m(QueryTable, {
          query: state.executedQuery,
          resp: state.queryResult,
          onClose: () => {
            state.executedQuery = undefined;
            state.queryResult = undefined;
            globals.rafScheduler.scheduleFullRedraw();
          },
        }),
        m(QueryHistoryComponent));
  },
});
