"use strict";
import {
  commands,
  Disposable,
  ViewColumn,
  Webview,
  WebviewPanel,
  WebviewPanelOnDidChangeViewStateEvent,
  window,
} from "vscode";
import { Command } from "../theia/command";

const emptyCommands: Disposable[] = [
  {
    dispose: function () {
      /* noop */
    },
  },
];

export abstract class WebviewBase implements Disposable {
  protected disposable: Disposable;
  private _disposablePanel: Disposable | undefined;
  private _panel: WebviewPanel | undefined;

  constructor(private id: string, private title:string, command: Command, private readonly _column?: ViewColumn) {
    this.disposable = Disposable.from(
      commands.registerCommand(command.cmd, this.onShowCommand, this)
    );
    this.load();
  }

  registerCommands(): Disposable[] {
    return emptyCommands;
  }

  renderHead?(): string | Promise<string>;
  renderBody?(): string | Promise<string>;
  renderEndOfBody?(): string | Promise<string>;

  dispose() {
    this.disposable.dispose();
    this._disposablePanel?.dispose();
  }

  protected onShowCommand() {
    void this.show(this._column);
  }

  private onPanelDisposed() {
    this._disposablePanel?.dispose();
    this._panel = undefined;
  }

  private onViewStateChanged(e: WebviewPanelOnDidChangeViewStateEvent) {
    console.log(
      `Webview(${this.id}).onViewStateChanged`,
      `active=${e.webviewPanel.active}, visible=${e.webviewPanel.visible}`
    );
  }

  get visible() {
    return this._panel?.visible ?? false;
  }

  hide() {
    this._panel?.dispose();
  }

  setTitle(title: string) {
    if (this._panel == null) return;

    this._panel.title = title;
  }

  onMessageReceive(message) {
    switch (message.command) {
      case "alert":
        window.showErrorMessage(message.text);
        return;
    }
  }

  async show(column: ViewColumn = ViewColumn.Beside): Promise<void> {
    if (this._panel == null) {
      this._panel = window.createWebviewPanel(
        this.id,
        this.title,
        { viewColumn: column, preserveFocus: false },
        {
          retainContextWhenHidden: true,
          enableFindWidget: true,
          enableCommandUris: true,
          enableScripts: true,
        }
      );

      this._disposablePanel = Disposable.from(
        this._panel,
        this._panel.onDidDispose(this.onPanelDisposed, this),
        this._panel.onDidChangeViewState(this.onViewStateChanged, this),
        this._panel.webview.onDidReceiveMessage(this.onMessageReceive, this),
        ...this.registerCommands()
      );

      this._panel.webview.html = await this.getHtml(this._panel.webview);
    } else {
      const html = await this.getHtml(this._panel.webview);

      // Reset the html to get the webview to reload
      this._panel.webview.html = "";
      this._panel.webview.html = html;

      this._panel.reveal(this._panel.viewColumn ?? ViewColumn.Active, false);
    }
  }

  /**
   * Must return the content displayed within the webViewPanel
   */
  abstract render(): string;
  /**
   * Method called at the end of first render
   */
  abstract load(): void;

  private async getHtml(webview: Webview): Promise<string> {
	  return this.render();
  }

}