/**
 * @module incident-sk
 * @description <h2><code>incident-sk</code></h2>
 *
 * <p>
 *   Displays a single Incident.
 * </p>
 *
 * @attr minimized {boolean} If not set then the incident is displayed in expanded
 *    mode, otherwise it is displayed in compact mode.
 *
 * @attr params {boolean} If set then the incident params are displayed, only
 *    applicable if minimized is true.
 *
 * @evt add-note Sent when the user adds a note to an incident.
 *    The detail includes the text of the note and the key of the incident.
 *
 *   <pre>
 *     detail {
 *       key: "12312123123",
 *       text: "blah blah blah",
 *     }
 *   </pre>
 *
 * @evt del-note Sent when the user deletes a note on an incident.
 *    The detail includes the index of the note and the key of the incident.
 *
 *   <pre>
 *     detail {
 *       key: "12312123123",
 *       index: 0,
 *     }
 *   </pre>
 *
 * @evt take Sent when the user wants the incident assigned to themselves.
 *    The detail includes the key of the incident.
 *
 *   <pre>
 *     detail {
 *       key: "12312123123",
 *     }
 *   </pre>
 *
 * @evt assign Sent when the user want to assign the incident to someone else.
 *    The detail includes the key of the incident.
 *
 *   <pre>
 *     detail {
 *       key: "12312123123",
 *     }
 *   </pre>
 *
 */
import { html, render, TemplateResult } from 'lit-html';
import { until } from 'lit-html/directives/until';
import { define } from '../../../elements-sk/modules/define';
import '../../../elements-sk/modules/icons/alarm-off-icon-sk';
import '../../../elements-sk/modules/icons/delete-icon-sk';
import '../../../elements-sk/modules/icons/thumbs-up-down-icon-sk';
import '../../../infra-sk/modules/clipboard-sk';
import '../silence-sk';

import { $$ } from '../../../infra-sk/modules/dom';
import { diffDate, strDuration } from '../../../infra-sk/modules/human';
import { errorMessage } from '../../../elements-sk/modules/errorMessage';
import { jsonOrThrow } from '../../../infra-sk/modules/jsonOrThrow';
import { abbr, linkify, displayNotes } from '../am';
import * as paramset from '../paramset';
import {
  Silence,
  Incident,
  Params,
  RecentIncidentsResponse,
  Note,
} from '../json';

const MAX_MATCHING_SILENCES_TO_DISPLAY = 50;

const PARAMS_TO_DISPLAY_COPY_ICON = ['abbr', 'alertname', 'app', 'bot'];

class State {
  key: string = '';

  id: string = '';

  params: Params = {};

  start: number = 0;

  last_seen: number = 0;

  active: boolean = false;

  notes: Note[] = [];
}

export class IncidentSk extends HTMLElement {
  private silences: Silence[] = [];

  private displaySilencesWithComments: boolean = false;

  private flaky: boolean = false;

  private recently_expired_silence: boolean = false;

  private state: State = {
    key: '',
    id: '',
    params: {},
    start: 0,
    last_seen: 0,
    active: false,
    notes: [],
  };

  private static template = (ele: IncidentSk) => html`
    <h2 class=${ele.classOfH2()}>
      ${ele.state.params.alertname} ${abbr(ele.state.params.abbr)}
      ${ele.displayRecentlyExpired(ele.recently_expired_silence)}
      ${ele.displayFlakiness(ele.flaky)}
    </h2>
    <section class="detail">
      ${ele.actionButtons()}
      <table class="timing">
        <tr>
          <th>Started</th>
          <td title=${new Date(ele.state.start * 1000).toLocaleString()}>
            ${diffDate(ele.state.start * 1000)}
          </td>
        </tr>
        ${ele.lastSeen()} ${ele.duration()}
      </table>
      <table class="params">
        ${ele.table()}
      </table>
      ${displayNotes(ele.state.notes, ele.state.key, 'del-note')}
      <section class="addNote">
        <textarea rows="2" cols="80"></textarea>
        <button @click=${ele.addNote}>Submit</button>
      </section>
      <section class="matchingSilences">
        <span class="matchingSilencesHeaders">
          <h3>Matching Silences</h3>
          <checkbox-sk
            ?checked=${ele.displaySilencesWithComments}
            @click=${ele.toggleSilencesWithComments}
            label="Show only silences with comments">
          </checkbox-sk>
        </span>
        ${ele.matchingSilences()}
      </section>
      <section class="history">
        <h3>History</h3>
        ${until(ele.history(), html`<div class="loading">Loading...</div>`)}
      </section>
    </section>
  `;

  /** @prop incident_state An Incident. */
  get incident_state(): State {
    return this.state;
  }

  set incident_state(val: State) {
    this.state = val;
    this._render();
  }

  /** @prop incident_silences The list of active silences. */
  get incident_silences(): Silence[] {
    return this.silences;
  }

  set incident_silences(val: Silence[]) {
    this._render();
    this.silences = val;
  }

  /** @prop recently_expired_silence Whether silence recently expired. */
  get incident_has_recently_expired_silence(): boolean {
    return this.recently_expired_silence;
  }

  set incident_has_recently_expired_silence(val: boolean) {
    // No need to render again if value is same as old value.
    if (val !== this.recently_expired_silence) {
      this.recently_expired_silence = val;
      this._render();
    }
  }

  /** @prop flaky Whether this incident has been flaky. */
  get incident_flaky(): boolean {
    return this.flaky;
  }

  set incident_flaky(val: boolean) {
    // No need to render again if value is same as old value.
    if (val !== this.flaky) {
      this.flaky = val;
      this._render();
    }
  }

  private classOfH2(): string {
    if (!this.state.active) {
      return 'inactive';
    }
    if (this.state.params.assigned_to) {
      return 'assigned';
    }
    return '';
  }

  private table(): TemplateResult[] {
    const params = this.state.params;
    const keys = Object.keys(params);
    keys.sort();
    return keys
      .filter((k) => !k.startsWith('__'))
      .map(
        (k) => html`
          <tr>
            <th>${k}</th>
            <td>
              <span class="respect-newlines">${linkify(params[k])}</span>
              ${this.maybeDisplayCopyIcon(k)}
            </td>
          </tr>
        `
      );
  }

  private maybeDisplayCopyIcon(k: string): TemplateResult {
    if (PARAMS_TO_DISPLAY_COPY_ICON.includes(k)) {
      return html`<clipboard-sk value=${this.state.params[k]}></clipboard-sk>`;
    }
    return html``;
  }

  private actionButtons(): TemplateResult {
    if (this.state.active) {
      let assignToOwnerButton = html``;
      if (this.state.params.owner) {
        assignToOwnerButton = html`<button @click=${this.assignToOwner}>
          Assign to Owner
        </button>`;
      }
      return html`<section class="assign">
        <button @click=${this.take}>Take</button>
        ${assignToOwnerButton}
        <button @click=${this.assign}>Assign</button>
      </section>`;
    }
    return html``;
  }

  private matchingSilences(): TemplateResult[] {
    if (this.hasAttribute('minimized')) {
      return [];
    }
    // Filter out silences whose paramsets do not match and
    // which have no notes if displaySilencesWithComments is true.
    const filteredSilences = this.silences.filter(
      (silence: Silence) =>
        paramset.match(silence.param_set, this.state.params) &&
        !(
          this.displaySilencesWithComments &&
          this.doesSilenceHaveNoNotes(silence)
        )
    );
    const ret = filteredSilences
      .slice(0, MAX_MATCHING_SILENCES_TO_DISPLAY)
      .map(
        (silence: Silence) =>
          html`<silence-sk
            .silence_state=${silence}
            collapsable
            collapsed></silence-sk>`
      );
    if (!ret.length) {
      ret.push(html`<div class="nosilences">None</div>`);
    }
    return ret;
  }

  private doesSilenceHaveNoNotes(silence: Silence): boolean {
    return (
      !silence.notes ||
      (silence.notes.length === 1 && silence.notes[0].text === '')
    );
  }

  private lastSeen(): TemplateResult {
    if (this.state.active) {
      return html``;
    }
    return html`<tr>
      <th>Last Seen</th>
      <td title=${new Date(this.state.last_seen * 1000).toLocaleString()}>
        ${diffDate(this.state.last_seen * 1000)}
      </td>
    </tr>`;
  }

  private duration(): TemplateResult {
    if (this.state.active) {
      return html``;
    }
    return html`<tr>
      <th>Duration</th>
      <td>${strDuration(this.state.last_seen - this.state.start)}</td>
    </tr>`;
  }

  private history(): Promise<any> {
    if (
      this.hasAttribute('minimized') ||
      this.state.id === '' ||
      this.state.key === ''
    ) {
      return Promise.resolve();
    }
    return fetch(
      `/_/recent_incidents?id=${this.state.id}&key=${this.state.key}`,
      {
        headers: {
          'content-type': 'application/json',
        },
        credentials: 'include',
        method: 'GET',
      }
    )
      .then(jsonOrThrow)
      .then((json: RecentIncidentsResponse) => {
        const incidents = json.incidents || [];
        this.incident_flaky = json.flaky;
        this.incident_has_recently_expired_silence =
          json.recently_expired_silence;
        return incidents.map(
          (i: Incident) =>
            html`<incident-sk .incident_state=${i} minimized></incident-sk>`
        );
      })
      .catch(errorMessage);
  }

  private toggleSilencesWithComments(e: Event): void {
    // This prevents a double event from happening.
    e.preventDefault();
    this.displaySilencesWithComments = !this.displaySilencesWithComments;
    this._render();
  }

  private displayRecentlyExpired(
    recentlyExpiredSilence: boolean
  ): TemplateResult {
    if (recentlyExpiredSilence) {
      return html`<alarm-off-icon-sk
        title="This alert has a recently expired silence"></alarm-off-icon-sk>`;
    }
    return html``;
  }

  private displayFlakiness(flaky: boolean): TemplateResult {
    if (flaky) {
      return html`<thumbs-up-down-icon-sk
        title="This alert is possibly flaky"></thumbs-up-down-icon-sk>`;
    }
    return html``;
  }

  private take(): void {
    const detail = {
      key: this.state.key,
    };
    this.dispatchEvent(
      new CustomEvent('take', { detail: detail, bubbles: true })
    );
  }

  private assignToOwner(): void {
    const detail = {
      key: this.state.key,
    };
    this.dispatchEvent(
      new CustomEvent('assign-to-owner', { detail: detail, bubbles: true })
    );
  }

  private assign(): void {
    const detail = {
      key: this.state.key,
    };
    this.dispatchEvent(
      new CustomEvent('assign', { detail: detail, bubbles: true })
    );
  }

  private addNote(): void {
    const textarea = $$('textarea', this) as HTMLInputElement;
    const detail = {
      key: this.state.key,
      text: textarea.value,
    };
    this.dispatchEvent(
      new CustomEvent('add-note', { detail: detail, bubbles: true })
    );
    textarea.value = '';
  }

  private _render(): void {
    if (!this.state) {
      return;
    }
    render(IncidentSk.template(this), this, { eventContext: this });
  }
}

define('incident-sk', IncidentSk);
