/*
 * 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 {
  AfterViewInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  EventEmitter,
  Input,
  NgZone,
  OnChanges,
  OnDestroy,
  Output,
  SimpleChanges
} from '@angular/core';

import { editor as MonacoEditor, IDisposable } from 'monaco-editor';
import IStandaloneCodeEditor = MonacoEditor.IStandaloneCodeEditor;
import IEditor = monaco.editor.IEditor;

import { InterpreterBindingItem } from '@zeppelin/sdk';
import { CompletionService, MessageService } from '@zeppelin/services';

import { pt2px } from '@zeppelin/utility/css-unit-conversion';
import { NotebookParagraphControlComponent } from '../control/control.component';

@Component({
  selector: 'zeppelin-notebook-paragraph-code-editor',
  templateUrl: './code-editor.component.html',
  styleUrls: ['./code-editor.component.less'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class NotebookParagraphCodeEditorComponent implements OnChanges, OnDestroy, AfterViewInit {
  // TODO(hsuanxyz):
  //  1. cursor position
  @Input() readOnly = false;
  @Input() language = 'text';
  @Input() paragraphControl: NotebookParagraphControlComponent;
  @Input() lineNumbers = false;
  @Input() focus = false;
  @Input() collaborativeMode = false;
  @Input() text: string;
  @Input() fontSize: number;
  @Input() dirty = false;
  @Input() interpreterBindings: InterpreterBindingItem[] = [];
  @Input() pid: string;
  @Output() readonly textChanged = new EventEmitter<string>();
  @Output() readonly editorBlur = new EventEmitter<void>();
  @Output() readonly editorFocus = new EventEmitter<void>();
  private editor: IStandaloneCodeEditor;
  private monacoDisposables: IDisposable[] = [];
  height = 0;
  interpreterName: string;

  autoAdjustEditorHeight() {
    if (this.editor) {
      this.ngZone.run(() => {
        this.height =
          this.editor.getTopForLineNumber(Number.MAX_SAFE_INTEGER) + this.editor.getConfiguration().lineHeight * 2;
        this.editor.layout();
        this.cdr.markForCheck();
      });
    }
  }

  initEditorListener() {
    const editor = this.editor;
    this.monacoDisposables.push(
      editor.onDidFocusEditorText(() => {
        this.editorFocus.emit();
      }),
      editor.onDidBlurEditorText(() => {
        this.editorBlur.emit();
      }),

      editor.onDidChangeModelContent(() => {
        this.ngZone.run(() => {
          this.text = editor.getModel().getValue();
          this.textChanged.emit(this.text);
          this.setParagraphMode(true);
          this.autoAdjustEditorHeight();
          setTimeout(() => {
            this.autoAdjustEditorHeight();
          });
        });
      })
    );
  }

  setEditorValue() {
    if (this.editor && this.editor.getModel() && this.editor.getModel().getValue() !== this.text) {
      this.editor.getModel().setValue(this.text || '');
    }
  }

  initializedEditor(editor: IEditor) {
    this.editor = editor as IStandaloneCodeEditor;
    this.editor.addCommand(
      monaco.KeyCode.Escape,
      () => {
        if (document.activeElement instanceof HTMLElement) {
          document.activeElement.blur();
        }
      },
      '!suggestWidgetVisible'
    );

    this.updateEditorOptions();
    this.setParagraphMode();
    this.initEditorListener();
    this.initEditorFocus();
    this.initCompletionService();
    this.setEditorValue();
    setTimeout(() => {
      this.autoAdjustEditorHeight();
    });
  }

  initCompletionService(): void {
    this.completionService.registerAsCompletionReceiver(this.editor.getModel(), this.paragraphControl.pid);
  }

  initEditorFocus() {
    if (this.focus && this.editor) {
      this.editor.focus();
    }
  }

  updateEditorOptions() {
    if (this.editor) {
      this.editor.updateOptions({
        readOnly: this.readOnly,
        fontSize: pt2px(this.fontSize),
        renderLineHighlight: this.focus ? 'all' : 'none',
        minimap: { enabled: false },
        lineNumbers: this.lineNumbers ? 'on' : 'off',
        glyphMargin: false,
        folding: false,
        scrollBeyondLastLine: false,
        contextmenu: false,
        matchBrackets: false
      });
    }
  }

  getInterpreterName(paragraphText: string) {
    const match = /^\s*%(.+?)(\s|\()/g.exec(paragraphText);
    if (match) {
      return match[1].trim();
      // get default interpreter name if paragraph text doesn't start with '%'
      // TODO(hsuanxyz): dig into the cause what makes interpreterBindings to have no element
    } else if (this.interpreterBindings && this.interpreterBindings.length !== 0) {
      return this.interpreterBindings[0].name;
    }
    return '';
  }

  setParagraphMode(changed = false) {
    if (this.editor && !changed) {
      const model = this.editor.getModel();
      if (this.language) {
        // TODO(hsuanxyz): config convertMap
        const convertMap = {
          sh: 'shell'
        };
        monaco.editor.setModelLanguage(model, convertMap[this.language] || this.language);
      }
    } else {
      const interpreterName = this.getInterpreterName(this.text);
      if (this.interpreterName !== interpreterName) {
        this.interpreterName = interpreterName;
        this.getEditorSetting(interpreterName);
      }
    }
  }

  getEditorSetting(interpreterName: string) {
    this.messageService.editorSetting(this.pid, interpreterName);
  }

  layout() {
    if (this.editor) {
      setTimeout(() => {
        this.editor.layout();
      });
    }
  }

  constructor(
    private cdr: ChangeDetectorRef,
    private ngZone: NgZone,
    private messageService: MessageService,
    private completionService: CompletionService
  ) {}

  ngOnChanges(changes: SimpleChanges): void {
    const { text, interpreterBindings, language, readOnly, focus, lineNumbers, fontSize } = changes;
    if (readOnly || focus || lineNumbers || fontSize) {
      this.updateEditorOptions();
    }
    if (focus) {
      this.initEditorFocus();
    }
    if (text) {
      this.setEditorValue();
    }

    if (interpreterBindings || language) {
      this.setParagraphMode();
    }
    if (text || fontSize) {
      this.autoAdjustEditorHeight();
    }
  }

  ngOnDestroy(): void {
    this.completionService.unregister(this.editor.getModel());
    this.monacoDisposables.forEach(d => d.dispose());
  }

  ngAfterViewInit(): void {}
}
