// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import { GraphView } from "../src/graph-view";
import { ScheduleView } from "../src/schedule-view";
import { SequenceView } from "../src/sequence-view";
import { SourceResolver } from "../src/source-resolver";
import { SelectionBroker } from "../src/selection-broker";
import { View, PhaseView } from "../src/view";

const multiviewID = "multiview";

const toolboxHTML = `
<div class="graph-toolbox">
  <select id="phase-select">
    <option disabled selected>(please open a file)</option>
  </select>
  <input id="search-input" type="text" title="search nodes for regex" alt="search node for regex" class="search-input"
    placeholder="find with regexp&hellip;">
  <label><input id="search-only-visible" type="checkbox" name="instruction-address" alt="Apply search to visible nodes only">only visible</label>
</div>`;

export class GraphMultiView extends View {
  sourceResolver: SourceResolver;
  selectionBroker: SelectionBroker;
  graph: GraphView;
  schedule: ScheduleView;
  sequence: SequenceView;
  selectMenu: HTMLSelectElement;
  currentPhaseView: PhaseView;

  createViewElement() {
    const pane = document.createElement("div");
    pane.setAttribute("id", multiviewID);
    pane.className = "viewpane";
    return pane;
  }

  constructor(id, selectionBroker, sourceResolver) {
    super(id);
    const view = this;
    view.sourceResolver = sourceResolver;
    view.selectionBroker = selectionBroker;
    const toolbox = document.createElement("div");
    toolbox.className = "toolbox-anchor";
    toolbox.innerHTML = toolboxHTML;
    view.divNode.appendChild(toolbox);
    const searchInput = toolbox.querySelector("#search-input") as HTMLInputElement;
    const onlyVisibleCheckbox = toolbox.querySelector("#search-only-visible") as HTMLInputElement;
    searchInput.addEventListener("keyup", e => {
      if (!view.currentPhaseView) return;
      view.currentPhaseView.searchInputAction(searchInput, e, onlyVisibleCheckbox.checked);
    });
    view.divNode.addEventListener("keyup", (e: KeyboardEvent) => {
      if (e.keyCode == 191) { // keyCode == '/'
        searchInput.focus();
      }
    });
    searchInput.setAttribute("value", window.sessionStorage.getItem("lastSearch") || "");
    this.graph = new GraphView(this.divNode, selectionBroker, view.displayPhaseByName.bind(this),
      toolbox.querySelector(".graph-toolbox"));
    this.schedule = new ScheduleView(this.divNode, selectionBroker);
    this.sequence = new SequenceView(this.divNode, selectionBroker);
    this.selectMenu = toolbox.querySelector("#phase-select") as HTMLSelectElement;
  }

  initializeSelect() {
    const view = this;
    view.selectMenu.innerHTML = "";
    view.sourceResolver.forEachPhase(phase => {
      const optionElement = document.createElement("option");
      let maxNodeId = "";
      if (phase.type == "graph" && phase.highestNodeId != 0) {
        maxNodeId = ` ${phase.highestNodeId}`;
      }
      optionElement.text = `${phase.name}${maxNodeId}`;
      view.selectMenu.add(optionElement);
    });
    this.selectMenu.onchange = function (this: HTMLSelectElement) {
      const phaseIndex = this.selectedIndex;
      window.sessionStorage.setItem("lastSelectedPhase", phaseIndex.toString());
      view.displayPhase(view.sourceResolver.getPhase(phaseIndex));
    };
  }

  show() {
    super.show();
    this.initializeSelect();
    const lastPhaseIndex = +window.sessionStorage.getItem("lastSelectedPhase");
    const initialPhaseIndex = this.sourceResolver.repairPhaseId(lastPhaseIndex);
    this.selectMenu.selectedIndex = initialPhaseIndex;
    this.displayPhase(this.sourceResolver.getPhase(initialPhaseIndex));
  }

  displayPhase(phase, selection?: Set<any>) {
    if (phase.type == "graph") {
      this.displayPhaseView(this.graph, phase, selection);
    } else if (phase.type == "schedule") {
      this.displayPhaseView(this.schedule, phase, selection);
    } else if (phase.type == "sequence") {
      this.displayPhaseView(this.sequence, phase, selection);
    }
  }

  displayPhaseView(view: PhaseView, data, selection?: Set<any>) {
    const rememberedSelection = selection ? selection : this.hideCurrentPhase();
    view.initializeContent(data, rememberedSelection);
    this.divNode.classList.toggle("scrollable", view.isScrollable());
    this.currentPhaseView = view;
  }

  displayPhaseByName(phaseName, selection?: Set<any>) {
    const phaseId = this.sourceResolver.getPhaseIdByName(phaseName);
    this.selectMenu.selectedIndex = phaseId;
    this.displayPhase(this.sourceResolver.getPhase(phaseId), selection);
  }

  hideCurrentPhase() {
    let rememberedSelection = null;
    if (this.currentPhaseView != null) {
      rememberedSelection = this.currentPhaseView.detachSelection();
      this.currentPhaseView.hide();
      this.currentPhaseView = null;
    }
    return rememberedSelection;
  }

  onresize() {
    if (this.currentPhaseView) this.currentPhaseView.onresize();
  }

  detachSelection() {
    return null;
  }
}