// Copyright (C) 2023 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 {indentWithTab} from '@codemirror/commands';
import {Transaction} from '@codemirror/state';
import {oneDarkTheme} from '@codemirror/theme-one-dark';
import {keymap} from '@codemirror/view';
import {basicSetup, EditorView} from 'codemirror';
import m from 'mithril';

export interface EditorAttrs {
  // Initial state for the editor.
  initialText?: string;

  // Changing generation is used to force resetting of the editor state
  // to the current value of initialText.
  generation?: number;

  // Callback for the Ctrl/Cmd + Enter key binding.
  onExecute?: (text: string) => void;

  // Callback for every change to the text.
  onUpdate?: (text: string) => void;
}

export class Editor implements m.ClassComponent<EditorAttrs> {
  private editorView?: EditorView;
  private generation?: number;

  oncreate({dom, attrs}: m.CVnodeDOM<EditorAttrs>) {
    const keymaps = [indentWithTab];
    const onExecute = attrs.onExecute;
    const onUpdate = attrs.onUpdate;

    if (onExecute) {
      keymaps.push({
        key: 'Mod-Enter',
        run: (view: EditorView) => {
          const state = view.state;
          const selection = state.selection;
          let text = state.doc.toString();
          if (!selection.main.empty) {
            let selectedText = '';

            for (const r of selection.ranges) {
              selectedText += text.slice(r.from, r.to);
            }

            text = selectedText;
          }
          onExecute(text);
          return true;
        },
      });
    }

    let dispatch;
    if (onUpdate) {
      dispatch = (tr: Transaction, view: EditorView) => {
        view.update([tr]);
        const text = view.state.doc.toString();
        onUpdate(text);
      };
    }

    this.generation = attrs.generation;

    this.editorView = new EditorView({
      doc: attrs.initialText ?? '',
      extensions: [
        keymap.of(keymaps),
        oneDarkTheme,
        basicSetup,
      ],
      parent: dom,
      dispatch,
    });
  }

  onupdate({attrs}: m.CVnodeDOM<EditorAttrs>): void {
    const {initialText, generation} = attrs;
    const editorView = this.editorView;
    if (editorView && this.generation !== generation) {
      const state = editorView.state;
      editorView.dispatch(state.update(
        {changes: {from: 0, to: state.doc.length, insert: initialText}}));
      this.generation = generation;
    }
  }

  onremove(): void {
    if (this.editorView) {
      this.editorView.destroy();
      this.editorView = undefined;
    }
  }

  view({}: m.Vnode<EditorAttrs, this>): void|m.Children {
    return m('.pf-editor');
  }
}
