/**
 * @module module/triage-page-sk
 * @description <h2><code>triage-page-sk</code></h2>
 *
 * Allows triaging clusters.
 *
 * TODO(jcgregorio) Needs working demo page and tests.
 *
 */
import dialogPolyfill from 'dialog-polyfill';
import { define } from 'elements-sk/define';
import { equals, deepCopy } from 'common-sk/modules/object';
import { fromObject } from 'common-sk/modules/query';
import { html } from 'lit-html';
import { jsonOrThrow } from 'common-sk/modules/jsonOrThrow';
import { stateReflector } from 'common-sk/modules/stateReflector';
import { HintableObject } from 'common-sk/modules/hintable';
import { errorMessage } from '../errorMessage';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import {
  RegressionRangeRequest,
  RegressionRow,
  Subset,
  RegressionRangeResponse,
  FullSummary,
  Regression,
  FrameResponse,
  ClusterSummary,
  Current,
  TriageRequest,
  TriageResponse,
} from '../json';

import 'elements-sk/spinner-sk';
import 'elements-sk/styles/buttons';
import 'elements-sk/styles/select';

import '../cluster-summary2-sk';
import '../commit-detail-sk';
import '../day-range-sk';
import '../triage-status-sk';
import { TriageStatusSkStartTriageEventDetails } from '../triage-status-sk/triage-status-sk';
import {
  ClusterSummary2SkTriagedEventDetail,
  ClusterSummary2SkOpenKeysEventDetail,
} from '../cluster-summary2-sk/cluster-summary2-sk';
import { DayRangeSkChangeDetail } from '../day-range-sk/day-range-sk';

function _full_summary(
  frame: FrameResponse,
  summary: ClusterSummary,
): FullSummary {
  return {
    frame,
    summary,
    triage: {
      message: '',
      status: 'untriaged',
    },
  };
}

interface State {
  begin: number;
  end: number;
  subset: Subset;
  filter: string; // Legacy query parameter alias for alert_filter.
  alert_filter: string;
}

interface ValueOptions {
  value: string;
  title: string;
  display: string;
}

export class TriagePageSk extends ElementSk {
  private state: State;

  private triageInProgress: boolean;

  private refreshRangeInProgress: boolean;

  private statusIntervalID: number;

  private firstConnect: boolean;

  private reg: RegressionRangeResponse;

  private dialogState: Partial<TriageStatusSkStartTriageEventDetails> = {};

  private lastState: Partial<State> = {};

  private dialog: HTMLDialogElement | null = null;

  private allFilterOptions: ValueOptions[] = [];

  private currentClusteringStatus: Current[] = [];

  constructor() {
    super(TriagePageSk.template);
    const now = Math.floor(Date.now() / 1000);

    // The state to reflect to the URL, also the body of the POST request
    // we send to /_/reg/.
    this.state = {
      begin: now - 2 * 7 * 24 * 60 * 60, // 2 weeks.
      end: now,
      subset: 'untriaged',
      alert_filter: 'ALL',
      filter: '',
    };

    this.reg = {
      header: [],
      table: [],
      categories: [],
    };

    this.allFilterOptions = [];

    this.triageInProgress = false;

    this.refreshRangeInProgress = false;

    // The ID of the setInterval that is updating _currentClusteringStatus.
    this.statusIntervalID = 0;

    this.firstConnect = false;
  }

  private static template = (ele: TriagePageSk) => html`
    <header>
      <details>
        <summary>
          Filter
        </summary>
        <h3>Which commits to display.</h3>
        <select @input=${ele.commitsChange}>
          <option
            ?selected=${ele.state.subset === 'all'}
            value="all"
            title="Show results for all commits in the time range."
          >
            All
          </option>
          <option
            ?selected=${ele.state.subset === 'regressions'}
            value="regressions"
            title="Show only the commits with regressions in the given time range regardless of triage status."
          >
            Regressions
          </option>
          <option
            ?selected=${ele.state.subset === 'untriaged'}
            value="untriaged"
            title="Show only commits with untriaged regressions in the given time range."
          >
            Untriaged
          </option>
        </select>

        <h3>Which alerts to display.</h3>

        <select @input=${ele.filterChange}>
          ${TriagePageSk.allFilters(ele)}
        </select>
      </details>
      <details>
        <summary>
          Range
        </summary>
        <day-range-sk
          @day-range-change=${ele.rangeChange}
          begin=${ele.state.begin}
          end=${ele.state.end}
        ></day-range-sk>
      </details>
      <details @toggle=${ele.toggleStatus}>
        <summary>
          Status
        </summary>
        <div>
          <p>The current work on detecting regressions:</p>
          <div class="status"> ${TriagePageSk.statusItems(ele)} </div>
        </div>
      </details>
    </header>
    <spinner-sk
      ?active=${ele.triageInProgress || ele.refreshRangeInProgress}
    ></spinner-sk>

    <dialog>
      <cluster-summary2-sk
        @open-keys=${ele.openKeys}
        @triaged=${ele.triaged}
        .full_summary=${ele.dialogState!.full_summary}
        .triage=${ele.dialogState!.triage}
        .alert=${ele.dialogState!.alert}
      ></cluster-summary2-sk>
      <div class="buttons">
        <button @click=${ele.close}>Close</button>
      </div>
    </dialog>

    <table @start-triage=${ele.triage_start}>
      <tr>
        <th>Commit</th>
        ${TriagePageSk.headers(ele)}
      </tr>
      <tr>
        <th></th>
        ${TriagePageSk.subHeaders(ele)}
      </tr>
      ${TriagePageSk.rows(ele)}
    </table>
  `;

  private static rows = (ele: TriagePageSk) => ele.reg!.table!.map(
    (row, rowIndex) => html`
        <tr>
          <td class="fixed">
            <commit-detail-sk .cid=${row!.cid}></commit-detail-sk>
          </td>
          ${TriagePageSk.columns(ele, row!, rowIndex)}
        </tr>
      `,
  );

  private static columns = (
    ele: TriagePageSk,
    row: RegressionRow,
    rowIndex: number,
  ) => row.columns!.map((col, colIndex) => {
    const ret = [];

    if (ele.stepDownAt(colIndex)) {
      ret.push(html`
          <td class="cluster">
            ${TriagePageSk.lowCell(ele, rowIndex, col!, colIndex)}
          </td>
        `);
    }

    if (ele.stepUpAt(colIndex)) {
      ret.push(html`
          <td class="cluster">
            ${TriagePageSk.highCell(ele, rowIndex, col!, colIndex)}
          </td>
        `);
    }

    if (ele.notBoth(colIndex)) {
      ret.push(html` <td></td> `);
    }
    return ret;
  });

  private static lowCell = (
    ele: TriagePageSk,
    rowIndex: number,
    col: Regression,
    colIndex: number,
  ) => {
    if (col && col.low) {
      return html`
        <triage-status-sk
          .alert=${ele.alertAt(colIndex)}
          .cluster_type=${'low'}
          .full_summary=${_full_summary(col.frame!, col.low)}
          .triage=${col.low_status}
        ></triage-status-sk>
      `;
    }
    return html`
      <a
        title="No clusters found."
        href="/g/c/${ele.hashFrom(rowIndex)}?query=${ele.encQueryFrom(
      colIndex,
    )}"
      >
        ∅
      </a>
    `;
  };

  private static highCell = (
    ele: TriagePageSk,
    rowIndex: number,
    col: Regression,
    colIndex: number,
  ) => {
    if (col && col.high) {
      return html`
        <triage-status-sk
          .alert=${ele.alertAt(colIndex)}
          .cluster_type=${'high'}
          .full_summary=${_full_summary(col.frame!, col.high)}
          .triage=${col.high_status}
        ></triage-status-sk>
      `;
    }
    return html`
      <a
        title="No clusters found."
        href="/g/c/${ele.hashFrom(rowIndex)}?query=${ele.encQueryFrom(
      colIndex,
    )}"
      >
        ∅
      </a>
    `;
  };

  private static subHeaders = (ele: TriagePageSk) => ele.reg.header!.map((_, index) => {
    const ret = [];
    if (ele.stepDownAt(index)) {
      ret.push(html` <th>Low</th> `);
    }
    if (ele.stepUpAt(index)) {
      ret.push(html` <th>High</th> `);
    }
    // If we have only one of High or Low we stuff in an empty th to match
    // colspan=2 above.
    if (ele.notBoth(index)) {
      ret.push(html` <th></th> `);
    }
    return ret;
  });

  private static headers = (ele: TriagePageSk) => ele.reg.header!.map((item) => {
    let displayName = item!.display_name;
    if (!item!.display_name) {
      displayName = item!.query.slice(0, 10);
    }
    // The colspan=2 is important since we will have two columns under each
    // header, one for high and one for low.
    return html`
        <th colspan="2">
          <a href="/a/?${item!.id_as_string}">${displayName}</a>
        </th>
      `;
  });

  private static statusItems = (ele: TriagePageSk) => ele.currentClusteringStatus.map(
    (item) => html`
        <table>
          <tr>
            <th>Alert</th>
            <td>
              <a href="/a/?${item.alert!.id_as_string}">
                ${item.alert!.display_name}
              </a>
            </td>
          </tr>
          <tr>
            <th>Commit</th>
            <td><commit-detail-sk .cid=${item.commit}></commit-detail-sk></td>
          </tr>
          <tr>
            <th>Step</th>
            <td>${item.message}</td>
          </tr>
        </table>
      `,
  );

  private static allFilters = (ele: TriagePageSk) => ele.allFilterOptions.map(
    (o) => html`
        <option
          ?selected=${ele.state.alert_filter === o.value}
          value=${o.value}
          title=${o.title}
        >
          ${o.display}
        </option>
      `,
  );

  connectedCallback(): void {
    super.connectedCallback();
    if (this.firstConnect) {
      return;
    }
    this.firstConnect = true;

    this._render();
    this.dialog = this.querySelector('triage-page-sk > dialog');
    dialogPolyfill.registerDialog(this.querySelector('dialog')!);
    this.stateHasChanged = stateReflector(
      () => (this.state as unknown) as HintableObject,
      (state) => {
        this.state = (state as unknown) as State;
        // Support the legacy query parameter.
        if (this.state.filter) {
          this.state.alert_filter = this.state.filter;
        }
        this._render();
        this.updateRange();
      },
    );
  }

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  private stateHasChanged = () => {};

  private commitsChange(e: InputEvent) {
    this.state.subset = (e.target! as HTMLInputElement).value as Subset;
    this.updateRange();
    this.stateHasChanged();
  }

  private filterChange(e: InputEvent) {
    this.state.alert_filter = (e.target! as HTMLInputElement).value;
    this.updateRange();
    this.stateHasChanged();
  }

  private toggleStatus(e: InputEvent) {
    if ((e.target! as HTMLDetailsElement).open) {
      this.statusIntervalID = window.setInterval(() => this.pollStatus(), 5000);
      this.pollStatus();
    } else {
      window.clearInterval(this.statusIntervalID);
    }
  }

  private pollStatus() {
    fetch('/_/reg/current')
      .then(jsonOrThrow)
      .then((json: Current[]) => {
        this.currentClusteringStatus = json;
        this._render();
      })
      .catch(errorMessage);
  }

  private triage_start(e: CustomEvent<TriageStatusSkStartTriageEventDetails>) {
    this.dialogState = e.detail;
    this._render();
    this.dialog!.showModal();
  }

  private triaged(e: CustomEvent<ClusterSummary2SkTriagedEventDetail>) {
    e.stopPropagation();
    const body: TriageRequest = {
      cid: e.detail.columnHeader.offset,
      triage: e.detail.triage,
      alert: this.dialogState!.alert!,
      cluster_type: this.dialogState!.cluster_type!,
    };
    this.dialog!.close();
    this._render();
    if (this.triageInProgress) {
      errorMessage('A triage request is in progress.');
      return;
    }
    this.triageInProgress = true;
    fetch('/_/triage/', {
      method: 'POST',
      body: JSON.stringify(body),
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then(jsonOrThrow)
      .then((json: TriageResponse) => {
        this.triageInProgress = false;
        this._render();
        if (json.bug) {
          // Open the bug reporting page in a new window.
          window.open(json.bug, '_blank');
        }
      })
      .catch((msg) => {
        if (msg) {
          errorMessage(msg, 10000);
        }
        this.triageInProgress = false;
        this._render();
      });
  }

  private close() {
    this.dialog!.close();
  }

  private stepUpAt(index: number) {
    const dir = this.reg.header![index]!.direction;
    return dir === 'UP' || dir === 'BOTH';
  }

  private stepDownAt(index: number) {
    const dir = this.reg.header![index]!.direction;
    return dir === 'DOWN' || dir === 'BOTH';
  }

  private notBoth(index: number) {
    return this.reg.header![index]!.direction !== 'BOTH';
  }

  private alertAt(index: number) {
    return this.reg.header![index];
  }

  private encQueryFrom(colIndex: number) {
    return encodeURIComponent(this.reg.header![colIndex]!.query);
  }

  private hashFrom(rowIndex: number) {
    return this.reg.table![rowIndex]!.cid!.offset;
  }

  private openKeys(e: CustomEvent<ClusterSummary2SkOpenKeysEventDetail>) {
    const query = {
      keys: e.detail.shortcut,
      begin: e.detail.begin,
      end: e.detail.end,
      xbaroffset: e.detail.xbar.offset,
      num_commits: 50,
      request_type: 1,
    };
    window.open(`/e/?${fromObject(query)}`, '_blank');
  }

  private rangeChange(e: CustomEvent<DayRangeSkChangeDetail>) {
    this.state.begin = Math.floor(e.detail.begin);
    this.state.end = Math.floor(e.detail.end);
    this.stateHasChanged();
    this.updateRange();
  }

  private updateRange() {
    if (this.refreshRangeInProgress) {
      return;
    }
    if (
      equals(
        (this.lastState! as unknown) as HintableObject,
        (this.state as unknown) as HintableObject,
      )
    ) {
      return;
    }
    this.lastState = deepCopy(this.state);
    this.refreshRangeInProgress = true;
    this._render();
    const body: RegressionRangeRequest = this.state;
    fetch('/_/reg/', {
      method: 'POST',
      body: JSON.stringify(body),
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then(jsonOrThrow)
      .then((json: RegressionRangeResponse) => {
        this.refreshRangeInProgress = false;
        this.reg = json;
        this.calc_all_filter_options();
        this._render();
      })
      .catch((msg) => {
        if (msg) {
          errorMessage(msg, 10000);
        }
        this.refreshRangeInProgress = false;
        this._render();
      });
  }

  private calc_all_filter_options() {
    const opts = [
      {
        value: 'ALL',
        title: 'Show all alerts.',
        display: 'Show all alerts.',
      },
      {
        value: 'OWNER',
        title:
          "Show only the alerts owned by the logged in user (or all alerts if the user doesn't own any alerts).",
        display: 'Show alerts you own.',
      },
    ];
    if (this.reg && this.reg.categories) {
      this.reg.categories.forEach((cat) => {
        const displayName = cat || '(default)';
        opts.push({
          value: `cat:${cat}`,
          title: `Show only the alerts in the ${displayName} category.`,
          display: `Category: ${displayName}`,
        });
      });
    }
    this.allFilterOptions = opts;
  }
}

define('triage-page-sk', TriagePageSk);
