/**
 * @module alert-manager-sk
 * @description <h2><code>alert-manager-sk</code></h2>
 *
 *   The main application element for am.skia.org.
 *
 */
import { define } from '../../../elements-sk/modules/define';
import '../../../elements-sk/modules/checkbox-sk';
import '../../../elements-sk/modules/error-toast-sk';
import '../../../elements-sk/modules/icons/alarm-off-icon-sk';
import '../../../elements-sk/modules/icons/comment-icon-sk';
import '../../../elements-sk/modules/icons/notifications-icon-sk';
import '../../../elements-sk/modules/icons/person-icon-sk';
import '../../../elements-sk/modules/spinner-sk';
import '../../../elements-sk/modules/tabs-panel-sk';
import '../../../elements-sk/modules/tabs-sk';
import '../../../elements-sk/modules/toast-sk';

import '../incident-sk';
import '../bot-chooser-sk';
import '../email-chooser-sk';
import '../silence-sk';

import { diffDate } from '../../../infra-sk/modules/human';
import { CheckOrRadio } from '../../../elements-sk/modules/checkbox-sk/checkbox-sk';
import { HintableObject } from '../../../infra-sk/modules/hintable';
import { $, $$ } from '../../../infra-sk/modules/dom';
import { errorMessage } from '../../../elements-sk/modules/errorMessage';
import { html, render, TemplateResult } from 'lit-html';
import { jsonOrThrow } from '../../../infra-sk/modules/jsonOrThrow';
import { stateReflector } from '../../../infra-sk/modules/stateReflector';
import { SpinnerSk } from '../../../elements-sk/modules/spinner-sk/spinner-sk';
import { Login } from '../../../infra-sk/modules/login';
import { BotChooserSk } from '../bot-chooser-sk/bot-chooser-sk';
import { EmailChooserSk } from '../email-chooser-sk/email-chooser-sk';
import '../../../infra-sk/modules/theme-chooser-sk';

import * as paramset from '../paramset';
import { displaySilence, expiresIn, getSilenceFullName } from '../am';

import {
  Silence, Incident, StatsRequest, Stat, IncidentsResponse, ParamSet, Params, IncidentsInRangeRequest, AuditLog,
} from '../json';

// Legal states.
const START = 'start';
const INCIDENT = 'incident';
const EDIT_SILENCE = 'edit_silence';
const VIEW_STATS = 'view_stats';
const VIEW_AUDITLOG = 'view_auditlog';

const MAX_SILENCES_TO_DISPLAY_IN_TAB = 50;

const BOT_CENTRIC_PARAMS = ['alertname', 'bot'];

class State {
  tab: number = 0; // The selected tab.

  alert_id: string = ''; // The selected alert (if any).
}

// This response structure comes from chrome-ops-rotation-proxy.appspot.com.
// We do not have access to the structure to generate TS.
interface RotationResp {
  emails: string[];
}

export class AlertManagerSk extends HTMLElement {
  private incidents: Incident[] = []; // All active incidents.

  private filterSilencesVal: string = '';

  private filterAuditLogsVal: string = '';

  private silences: Silence[] = []; // All active silences.

  private stats: Stat[] = []; // Last requested stats.

  private audit_logs: AuditLog[] = [];

  private stats_range = '1w';

  private incident_stats: Incident[] = []; // The incidents for a given stat.

  private rhs_state = START; // One of START, INCIDENT, or EDIT_SILENCE.

  private selected: Incident|Silence|null = null; // The selected incident, i.e. you clicked on the name.

  private checked = new Set(); // Checked incidents, i.e. you clicked the checkbox.

  private bots_to_incidents: Record<string, Incident[]> = {}; // Bot names to their incidents. Used in bot-centric view.

  private isBotCentricView = false; // Determines if bot-centric view is displayed on incidents tab.

  private current_silence: Silence|null = null; // A silence under construction.

  // Params to ignore when constructing silences.
  private ignored = ['__silence_state', 'description', 'id', 'swarming', 'assigned_to',
    'kubernetes_pod_name', 'instance', 'pod_template_hash', 'abbr_owner_regex',
    'controller_revision_hash'];

  private shift_pressed_during_click = false; // If the shift key was held down during the mouse click.

  private last_checked_incident: string|null = null; // Keeps track of the last checked incident. Used for multi-selecting incidents with shift.

  private incidents_notified: Record<string, boolean> = {}; // Keeps track of all incidents that were notified via desktop notifications.

  private incidentsToRecentlyExpired: Record<string, boolean> = {}; // Map of incident IDs to whether their silences recently expired.

  private user = 'barney@example.org';

  private infra_gardener = '';

  // State is reflected to the URL via stateReflector.
  private state: State = {
    tab: 0,
    alert_id: '',
  };

  private favicon: HTMLAnchorElement | null = null;

  private spinner: SpinnerSk | null = null;

  private emails: string[] = [];

  private helpDialog: HTMLDialogElement | null = null;

  constructor() {
    super();

    fetch('https://chrome-ops-rotation-proxy.appspot.com/current/grotation:skia-infra-gardener', { mode: 'cors' }).then(jsonOrThrow).then((json: RotationResp) => {
      this.infra_gardener = json.emails[0];
      this._render();
    });
    Login.then((loginstatus) => {
      this.user = loginstatus.Email;
      this._render();
    });
  }

  private static template = (ele: AlertManagerSk) => html`
<header>
  ${ele.infraGardener()}
  <theme-chooser-sk></theme-chooser-sk>
</header>
<dialog id=help>
  <h2>Keyboard Controls</h2>
  <table>
    <tr><td class=mono>'ArrowDown'</td><td>Move down the list of incidents.</td></tr>
    <tr><td class=mono>'ArrowUp'</td><td>Move up the list of incidents.</td></tr>
    <tr><td class=mono>'Space'</td><td>Check the incident to create a silence or to assign.</td></tr>
    <tr><td class=mono>'Shift+ArrowDown'</td><td>Check the below incident to create a silence (only if the current incident is checked).</td></tr>
    <tr><td class=mono>'Shift+ArrowUp'</td><td>Check the above incident to create a silence (only if the current incident is checked).</td></tr>
    <tr><td class=mono>'ArrowRight'</td><td>Move to the first textarea in RHS.</td></tr>
    <tr><td class=mono>'a'</td><td>Assign selected alert(s).</td></tr>
    <tr><td class=mono>'b'</td><td>Switches view from normal to bot-centric view.</td></tr>
    <tr><td class=mono>'1'</td><td>Switches to the "Mine" tab.</td></tr>
    <tr><td class=mono>'2'</td><td>Switches to the "Alerts" tab.</td></tr>
    <tr><td class=mono>'?'</td><td>Show help.</td></tr>
    <tr><td class=mono>'Esc'</td><td>Stop showing help.</td></tr>
  </table>
  <div class=footnote>
    Note: Keyboard controls only work in the 'Mine' and 'Alerts' tabs. 'Bot-centric view' is also not supported.
  </div>
</dialog>
<section class=nav>
  <tabs-sk @tab-selected-sk=${ele.tabSwitch} selected=${ele.state.tab}>
    <button>Mine</button>
    <button>Alerts</button>
    <button>Silences</button>
    <button>Stats</button>
    <button>Audit</button>
  </tabs-sk>
  <tabs-panel-sk>
    <section class=mine>
      <span class=selection-buttons>
        ${ele.displayAssignMultiple()}
        ${ele.displayClearSelections()}
      </span>
      ${ele.incidentList(ele.getMyIncidents(), false)}
    </section>
    <section class=incidents>
      ${ele.botCentricBtn()}
      <span class=selection-buttons>
        ${ele.displayAssignMultiple()}
        ${ele.displayClearSelections()}
      </span>
      ${ele.incidentList(ele.incidents, ele.isBotCentricView)}
    </section>
    <section class=silences>
      <input class=silences-filter placeholder="Filter silences" .value="${ele.filterSilencesVal}" @input=${(e: Event) => ele.filterSilencesEvent(e)}></input>
      <br/><br/>
      ${ele.silences.filter((silence: Silence) => getSilenceFullName(silence.param_set).includes(ele.filterSilencesVal)).slice(0, MAX_SILENCES_TO_DISPLAY_IN_TAB).map((i: Silence) => html`
        <h2 class=${ele.classOfSilenceH2(i)} @click=${() => ele.silenceClick(i)}>
          <span>
            ${displaySilence(i.param_set)}
          </span>
          <span>
            <span title='Expires in'>${expiresIn(i.active, i.created, i.duration)}</span>
            <comment-icon-sk title='This silence has notes.' class=${ele.hasNotes(i)}></comment-icon-sk>
            <span title='The number of active alerts that match this silence.'>${ele.numMatchSilence(i)}</span>
          </span>
        </h2>`)}
    </section>
    <section class=stats>
      ${ele.statsList()}
    </section>
    <section class=auditlogs>
      <input class=auditlogs-filter placeholder="Filter audit logs" .value="${ele.filterAuditLogsVal}" @input=${(e: Event) => ele.filterAuditLogsEvent(e)}></input>
    </section>
  </tabs-panel-sk>
</section>
<section class=edit>
  ${ele.rightHandSide()}
</section>
<footer>
  <spinner-sk id=busy></spinner-sk>
  <bot-chooser-sk id=bot-chooser></bot-chooser-sk>
  <email-chooser-sk id=email-chooser></email-chooser-sk>
  <error-toast-sk></error-toast-sk>
</footer>
`;

  connectedCallback(): void {
    this.requestDesktopNotificationPermission();

    this.addEventListener('save-silence', (e) => this.saveSilence((e as CustomEvent).detail.silence));
    this.addEventListener('archive-silence', (e) => this.archiveSilence((e as CustomEvent).detail.silence));
    this.addEventListener('reactivate-silence', (e) => this.reactivateSilence((e as CustomEvent).detail.silence));
    this.addEventListener('delete-silence', (e) => this.deleteSilence((e as CustomEvent).detail.silence));
    this.addEventListener('add-silence-note', (e) => this.addSilenceNote(e as CustomEvent));
    this.addEventListener('del-silence-note', (e) => this.delSilenceNote(e as CustomEvent));
    this.addEventListener('add-silence-param', (e) => this.addSilenceParam((e as CustomEvent).detail.silence));
    this.addEventListener('delete-silence-param', (e) => this.deleteSilenceParam((e as CustomEvent).detail.silence));
    this.addEventListener('modify-silence-param', (e) => this.modifySilenceParam((e as CustomEvent).detail.silence));
    this.addEventListener('add-note', (e) => this.addNote(e as CustomEvent));
    this.addEventListener('del-note', (e) => this.delNote(e as CustomEvent));
    this.addEventListener('take', (e) => this.take(e as CustomEvent));
    this.addEventListener('bot-chooser', () => this.botChooser());
    this.addEventListener('assign', (e) => this.assign(e as CustomEvent));
    this.addEventListener('assign-to-owner', (e) => this.assignToOwner(e as CustomEvent));
    // For keyboard navigation.
    document.addEventListener('keydown', (e) => this.keyDown(e));

    this.stateHasChanged = stateReflector(
      /* getState */ () => (this.state as unknown) as HintableObject,
      /* setState */ (newState) => {
        this.state = (newState as unknown) as State;
        // Set rhs_side to AUDIT_LOG if tab is on Audit.
        if (this.state.tab === 4) {
          this.getAuditLogs();
          this.rhs_state = VIEW_AUDITLOG;
        }
        this._render();
      },
    );

    this._render();

    this.helpDialog = $$('#help', this);
    this.spinner = $$('#busy', this) as SpinnerSk;
    this.favicon = $$('#favicon');

    this.spinner.active = true;
    this.poll(true);
  }

  private getMyIncidents(): Incident[] {
    return this.incidents.filter((i: Incident) => i.active
          && i.params.__silence_state !== 'silenced'
          && (this.user === this.infra_gardener
            || i.params.assigned_to === this.user
            || (i.params.owner === this.user && !i.params.assigned_to)));
  }

  private keyDown(e: KeyboardEvent) {
    // Ignore all tabs other than the mine and incident tabs.
    if (this.state.tab !== 0 && this.state.tab !== 1) {
      return;
    }

    // Too complicated to navigate through issues in bot centric view
    // because the layout of incidents is completely different than
    // the standard view.
    if (this.isBotCentricView) {
      return;
    }

    // Ignore IME composition events.
    if (e.isComposing || e.keyCode === 229) {
      return;
    }

    // Do not perform keyboard navigation if input/textarea/select are
    // selected.
    const focusedElem: Element | null = document.activeElement;
    const ignoreKeyboardNavigationInTags = ['input', 'textarea', 'select'];
    if (focusedElem && ignoreKeyboardNavigationInTags.includes(focusedElem.tagName.toLowerCase())) {
      return;
    }

    switch (e.key) {
      case '?':
        (this.helpDialog! as any).showModal();
        break;
      case 'ArrowUp':
        this.keyboardNavigateIncidents(e, true);
        break;
      case 'ArrowDown':
        this.keyboardNavigateIncidents(e, false);
        break;
      case 'ArrowRight':
        // Put focus on the 1st textarea on the page (if one exists).
        if ($('textarea') && $('textarea').length > 0) {
          ($('textarea')[0] as HTMLElement).focus();
        }
        break;
      case ' ':
        if (this.selected) {
          ($$(`#${this.selected!.key}`)! as HTMLElement).click();
        } else if (this.checked.size > 0) {
          // No incident was selected. Clear all the checked incidents and
          // start from the first incident.
          this.checked.clear();
          this.last_checked_incident = null;
          if (this.incidents.length > 0) {
            this.selected = this.incidents[0];
          }
          this._render();
        }
        e.preventDefault();
        break;
      case 'b':
        this.flipBotCentricView();
        break;
      case 'a':
        // If an alert is selected and nothing is checked then
        // check the selected alert before assigning it.
        if (this.selected && this.checked.size === 0) {
          ($$(`#${this.selected!.key}`)! as HTMLElement).click();
        }
        this.assignMultiple();
        break;
      case '1':
        this.keyboardNavigateTabs(0);
        break;
      case '2':
        this.keyboardNavigateTabs(1);
        break;
      default:
        break;
    }
  }

  private keyboardNavigateTabs(tabIndex: number) {
    this.state.tab = tabIndex;
    this.state.alert_id = '';
    this.selected = null;
    this.checked.clear();
    this.rhs_state = START;
    this.stateHasChanged();
    this._render();
  }

  private keyboardNavigateIncidents(e: KeyboardEvent, reverseDirection: boolean) {
    // If an alert is not selected or checked then the first incident in the
    // incidents array can be starting point.
    let foundStartingPoint = (this.selected === null) && (this.checked.size === 0);

    // Figure out which incidents we are looking at.
    let incidentsArray = this.incidents;
    if (this.state.tab === 0) {
      // Use "my" incidents if we are on the "Mine" tab.
      incidentsArray = this.getMyIncidents();
    }
    if (reverseDirection && !foundStartingPoint) {
      // We only want to reverse incidents if we have not yet
      // found a starting point else we will start with the
      // last alert.
      incidentsArray = incidentsArray.reverse();
    }

    for (const incident of incidentsArray) {
      if (foundStartingPoint) {
        const k = incident.key;
        // If shift key is pressed then check the incident if it is not already
        // checked.
        if (e.shiftKey && this.last_checked_incident) {
          if (this.checked.has(k)) {
            // This incident is already checked. Set it as the
            // last_checked_incident so we can proceed from here the next time.
            this.last_checked_incident = k;
          } else {
            // Check the incident.
            ($$(`#${k}`)! as HTMLElement).click();
          }
        } else {
          ($$(`#container-${k}`)! as HTMLElement).click();
        }
        break;
      }

      if (this.selected && this.selected.key === incident.key) {
        // We found the selected incident, the next incident in the iteration
        // is the one we need to process.
        foundStartingPoint = true;
      } else if (this.checked.size > 0 && this.last_checked_incident === incident.key) {
        // We found the last checked incident, the next incident in the
        // iteration is the one we need to process.
        foundStartingPoint = true;
      }
    }
  }

  // Call this anytime something in private state is changed. Will be replaced
  // with the real function once stateReflector has been setup.
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  private stateHasChanged = () => {};

  private classOfH2(incident: Incident): string {
    const ret = [];
    if (!incident.active) {
      ret.push('inactive');
    } else if (incident.params.__silence_state === 'silenced') {
      ret.push('silenced');
    } else if (incident.params.assigned_to) {
      ret.push('assigned');
    }
    if (this.selected && this.selected.key === incident.key) {
      ret.push('selected');
    }
    return ret.join(' ');
  }

  private classOfSilenceH2(silence: Silence): string {
    const ret = [];
    if (!silence.active) {
      ret.push('inactive');
    }
    if (this.selected && this.selected.key === silence.key) {
      ret.push('selected');
    }
    return ret.join(' ');
  }

  private editIncident(): TemplateResult {
    if (this.selected) {
      return html`<incident-sk .incident_silences=${this.silences} .incident_state=${this.selected}
        ></incident-sk>`;
    }
    return html``;
  }

  private editSilence(): TemplateResult {
    return html`<silence-sk .silence_state=${this.current_silence} .silence_incidents=${this.incidents}
      ></silence-sk>`;
  }

  private viewStats(): TemplateResult[] {
    return this.incident_stats.map((i, index) => html`<incident-sk .incident_state=${i} minimized params=${index === 0}></incident-sk>`);
  }

  private rightHandSide(): TemplateResult|TemplateResult[] {
    switch (this.rhs_state) {
      case START:
        return [];
      case INCIDENT:
        return this.editIncident();
      case EDIT_SILENCE:
        return this.editSilence();
      case VIEW_STATS:
        return this.viewStats();
      case VIEW_AUDITLOG:
        return this.viewAuditLogsTable();
      default:
        return [];
    }
  }

  private hasNotes(o: Incident| Silence): string {
    return (o.notes && o.notes.length > 0) ? '' : 'invisible';
  }

  private hasRecentlyExpiredSilence(incident: Incident): string {
    return (this.incidentsToRecentlyExpired[incident.id]) ? '' : 'invisible';
  }

  private displayIncident(incident: Incident): TemplateResult {
    const ret = [incident.params.alertname];
    const abbr = incident.params.abbr;
    if (abbr) {
      ret.push(` - ${abbr}`);
    }
    const fullIncident = ret.join(' ');
    let displayIncident = fullIncident;
    if (displayIncident.length > 33) {
      displayIncident = `${displayIncident.slice(0, 30)}...`;
    }
    return html`<span title="${fullIncident}">${displayIncident}</span>`;
  }

  private infraGardener(): TemplateResult {
    if (this.infra_gardener === this.user) {
      return html`<notifications-icon-sk title='You are the Infra Gardener, awesome!'></notifications-icon-sk>`;
    }
    return html``;
  }

  private assignedTo(incident: Incident): TemplateResult {
    if (incident.params.assigned_to === this.user) {
      return html`<person-icon-sk title='This item is assigned to you.'></person-icon-sk>`;
    } if (incident.params.assigned_to) {
      return html`<span class='assigned-circle' title='This item is assigned to ${incident.params.assigned_to}.'>${incident.params.assigned_to[0].toUpperCase()}</span>`;
    }
    return html``;
  }

  private populateBotsToIncidents(incidents: Incident[]): void {
    // Reset bots_to_incidents and populate it from scratch.
    this.bots_to_incidents = {};
    for (let i = 0; i < incidents.length; i++) {
      const incident = incidents[i];
      if (incident.params && incident.params.bot) {
        // Only consider active bot incidents that are not assigned or silenced.
        if (!incident.active || incident.params.__silence_state === 'silenced'
            || incident.params.assigned_to) {
          continue;
        }
        const botName = incident.params.bot;
        if (this.bots_to_incidents[botName]) {
          this.bots_to_incidents[botName].push(incident);
        } else {
          this.bots_to_incidents[botName] = [incident];
        }
      }
    }
  }

  private botCentricView(): TemplateResult[] {
    this.populateBotsToIncidents(this.incidents);
    const botsHTML: TemplateResult[] = [];
    Object.keys(this.bots_to_incidents).forEach((botName) => {
      botsHTML.push(html`
        <h2 class="bot-centric">
          <span class=noselect>
            <checkbox-sk class=bot-alert-checkbox ?checked=${this.isBotChecked(this.bots_to_incidents[botName])} @change=${this.check_selected} @click=${this.clickHandler} id=${botName}></checkbox-sk>
            <span class=bot-alert>
              ${botName}
              <span class=bot-incident-list>
                ${this.incidentListForBot(this.bots_to_incidents[botName])}
              </span>
            </span>
          </span>
        </h2>
      `);
    });
    return botsHTML;
  }

  // Checks to see if all the incidents for the bot are checked.
  private isBotChecked(incidents: Incident[]): boolean {
    for (let i = 0; i < incidents.length; i++) {
      if (!this.checked.has(incidents[i].key)) {
        return false;
      }
    }
    return true;
  }

  private incidentListForBot(incidents: Incident[]): TemplateResult {
    const incidentsHTML = incidents.map((i) => html`<li @click=${() => this.select(i)}>${i.params.alertname}</li>`);
    return html`<ul class=bot-incident-elem>${incidentsHTML}</ul>`;
  }

  private incidentList(incidents: Incident[], isBotCentricView: boolean): TemplateResult[] {
    if (isBotCentricView) {
      return this.botCentricView();
    }
    return incidents.map((i) => html`
        <h2 class=${this.classOfH2(i)} @click=${() => this.select(i)} id=container-${i.key}>
        <span class=noselect>
          <checkbox-sk ?checked=${this.checked.has(i.key)} @change=${this.check_selected} @click=${this.clickHandler} id=${i.key}></checkbox-sk>
          ${this.assignedTo(i)}
          ${this.displayIncident(i)}
        </span>
        <span>
          <alarm-off-icon-sk title='This incident has a recently expired silence' class=${this.hasRecentlyExpiredSilence(i)}></alarm-off-icon-sk>
          <comment-icon-sk title='This incident has notes.' class=${this.hasNotes(i)}></comment-icon-sk>
        </span>
        </h2>
      `);
  }

  private statsList(): TemplateResult[] {
    return this.stats.map((stat: Stat) => html`<h2 @click=${() => this.statsClick(stat.incident)}>${this.displayIncident(stat.incident)} <span>${stat.num}</span></h2>`);
  }

  private viewAuditLogsTable(): TemplateResult {
    return html`
      <table id=audit-logs-table>
        ${this.getAuditLogsRows()}
      </table>
    `;
  }

  private getAuditLogsRows(): TemplateResult[] {
    const filtered_audit_logs = this.audit_logs.filter((a) => a.body.includes(this.filterAuditLogsVal));
    return filtered_audit_logs.map((a) => html`
      <tr>
        <td>
          ${diffDate(a.timestamp * 1000)} ago
        </td>
        <td>
          ${a.action}
        </td>
        <td>
          ${a.user}
        </td>
        <td>
          ${a.body}
        </td>
      </tr>
    `);
  }

  private numMatchSilence(s: Silence): number {
    if (!this.incidents) {
      return 0;
    }
    return this.incidents.filter(
      (incident: Incident) => paramset.match(s.param_set, incident.params) && incident.active,
    ).length;
  }

  private displayClearSelections(): TemplateResult {
    return html`<button class=selection ?disabled=${this.checked.size === 0} @click=${this.clearSelections}>Clear selections</button>`;
  }

  private filterSilencesEvent(e: Event): void {
    this.filterSilencesVal = (e.target as HTMLInputElement).value;
    this._render();
  }

  private filterAuditLogsEvent(e: Event): void {
    this.filterAuditLogsVal = (e.target as HTMLInputElement).value;
    this._render();
  }

  private clearSelections(): void {
    this.checked = new Set();
    this._render();
  }

  private displayAssignMultiple(): TemplateResult {
    return html`<button class=selection ?disabled=${this.checked.size === 0} @click=${this.assignMultiple}>Assign ${this.checked.size} alerts</button>`;
  }

  private botCentricBtn(): TemplateResult {
    let buttonText;
    if (this.isBotCentricView) {
      buttonText = 'Switch to Normal view';
    } else {
      buttonText = 'Switch to Bot-centric view';
    }
    return html`<button @click=${this.flipBotCentricView}>${buttonText}</button>`;
  }

  private findParent(ele: HTMLElement|null, tagName: string): HTMLElement|null {
    while (ele && (ele.tagName !== tagName)) {
      ele = ele.parentElement;
    }
    return ele;
  }

  private poll(stopSpinner: boolean): void {
    const incidents = fetch('/_/incidents', {
      credentials: 'include',
    }).then(jsonOrThrow).then((json: IncidentsResponse) => {
      this.incidents = json.incidents || [];
      // If alert_id is specified and it is in supported rhs_states then display
      // an incident.
      if ((this.rhs_state === START || this.rhs_state === INCIDENT)
          && this.state.alert_id) {
        for (let i = 0; i < this.incidents.length; i++) {
          if (this.incidents[i].id === this.state.alert_id) {
            this.select(this.incidents[i]);
            break;
          }
        }
      }
      this.incidents = json.incidents || [];
      this.incidentsToRecentlyExpired = json.ids_to_recently_expired_silences || {};
    });

    const silences = fetch('/_/silences', {
      credentials: 'include',
    }).then(jsonOrThrow).then((json: Silence[]) => {
      this.silences = json;
    });

    const emails = fetch('/_/emails', {
      credentials: 'include',
    }).then(jsonOrThrow).then((json: string[]) => {
      this.emails = json;
    });

    Promise.all([incidents, silences, emails]).then(() => { this._render(); }).catch((msg) => {
      if (msg.resp) {
        msg.resp.text().then(errorMessage);
      } else {
        errorMessage(msg);
      }
    }).finally(() => {
      if (stopSpinner) {
        this.spinner!.active = false;
      }
      window.setTimeout(() => this.poll(false), 10000);
    });
  }

  private tabSwitch(e: CustomEvent): void {
    this.state.tab = e.detail.index;
    // Unset alert_id when switching tabs.
    this.state.alert_id = '';
    this.stateHasChanged();
    // Unset filters when switching tabs.
    this.filterSilencesVal = '';
    this.filterAuditLogsVal = '';

    // If tab is stats then load stats.
    if (e.detail.index === 3) {
      this.getStats();
    }
    // If tab is silences then display empty silence to populate from scratch.
    // This will go away if any existing silence is clicked on.
    if (e.detail.index === 2) {
      fetch('/_/new_silence', {
        credentials: 'include',
      }).then(jsonOrThrow).then((json: Silence) => {
        this.selected = null;
        this.current_silence = json;
        this.rhs_state = EDIT_SILENCE;
        this._render();
      }).catch(errorMessage);
    } else if (e.detail.index === 4) {
      // If tab is audit logs then load them.
      this.getAuditLogs();
      this.rhs_state = VIEW_AUDITLOG;
      this._render();
    } else {
      this.rhs_state = START;
      this._render();
    }
  }

  private clickHandler(e: KeyboardEvent): void {
    this.shift_pressed_during_click = e.shiftKey;
    e.stopPropagation();
  }

  private silenceClick(silence: Silence): void {
    this.current_silence = JSON.parse(JSON.stringify(silence)) as Silence;
    this.selected = silence;
    this.rhs_state = EDIT_SILENCE;
    this._render();
  }

  private statsClick(incident: Incident): void {
    this.selected = incident;
    this.incidentStats();
    this.rhs_state = VIEW_STATS;
  }

  // Update the paramset for a silence as Incidents are checked and unchecked.
  // TODO(jcgregorio) Remove this once checkbox-sk is fixed.
  private check_selected_impl(key: string, isChecked: boolean): void {
    if (isChecked) {
      this.last_checked_incident = key;
      this.checked.add(key);
      this.incidents.forEach((i) => {
        if (i.key === key) {
          paramset.add(this.current_silence!.param_set, i.params, this.ignored);
        }
      });
    } else {
      this.last_checked_incident = null;
      this.checked.delete(key);
      this.current_silence!.param_set = {};
      this.incidents.forEach((i) => {
        if (this.checked.has(i.key)) {
          paramset.add(this.current_silence!.param_set, i.params, this.ignored);
        }
      });
    }

    if (this.isBotCentricView) {
      this.make_bot_centric_param_set(this.current_silence!.param_set);
    }
    this.rhs_state = EDIT_SILENCE;
  }

  // Goes through the paramset and leaves only silence keys that are useful
  // in bot-centric view like 'alertname' and 'bot'.
  private make_bot_centric_param_set(target_paramset: ParamSet): void {
    Object.keys(target_paramset).forEach((key) => {
      if (BOT_CENTRIC_PARAMS.indexOf(key) === -1) {
        delete target_paramset[key];
      }
    });
  }

  private async check_selected(e: Event): Promise<void> {
    const checkbox = this.findParent(e.target as HTMLElement, 'CHECKBOX-SK') as CheckOrRadio;
    const incidents_to_check: string[] = [];
    if (this.isBotCentricView && this.bots_to_incidents
        && this.bots_to_incidents[checkbox.id]) {
      this.bots_to_incidents[checkbox.id].forEach((i) => {
        incidents_to_check.push(i.key);
      });
    } else {
      incidents_to_check.push(checkbox.id);
    }
    const checkSelectedImplFunc = () => {
      incidents_to_check.forEach((id) => {
        this.check_selected_impl(id, checkbox.checked);
      });
    };

    if (!this.checked.size) {
      // Request a new silence.
      try {
        const resp = await fetch('/_/new_silence', {
          credentials: 'include',
        });
        const silence: Silence = await jsonOrThrow(resp);
        this.selected = null;
        this.current_silence = silence;
        checkSelectedImplFunc();
      } catch (error: any) {
        errorMessage(error);
      }
    } else if (this.shift_pressed_during_click && this.last_checked_incident) {
      let foundStart = false;
      let foundEnd = false;
      // Find all incidents included in the range during shift click.
      const incidents_included_in_range: string[] = [];


      let incidents: Incident[] = [];
      if (this.state.tab === 0) {
        // Use "my" incidents if we are on the "Mine" tab.
        incidents = this.getMyIncidents();
      } else {
        // The incidents we go through for shift click selections will be
        // different for bot-centric vs normal view.
        incidents = this.isBotCentricView
          ? ([] as Incident[]).concat(...Object.values(this.bots_to_incidents))
          : this.incidents;
      }

      incidents.some((i) => {
        if (i.key === this.last_checked_incident
                || incidents_to_check.includes(i.key)) {
          if (!foundStart) {
            // This is the 1st time we have entered this block. This means we
            // found the first incident.
            foundStart = true;
          } else {
            // This is the 2nd time we have entered this block. This means we
            // found the last incident.
            foundEnd = true;
          }
        }
        if (foundStart) {
          incidents_included_in_range.push(i.key);
        }
        return foundEnd;
      });

      if (foundStart && foundEnd) {
        incidents_included_in_range.forEach((key) => {
          this.check_selected_impl(key, true);
        });
      } else {
        // Could not find start and/or end incident. Only check the last
        // clicked.
        checkSelectedImplFunc();
      }
    } else {
      checkSelectedImplFunc();
    }
    this._render();
  }

  private select(incident: Incident): void {
    this.state.alert_id = incident.id;
    this.stateHasChanged();

    this.rhs_state = INCIDENT;
    this.checked = new Set();
    this.selected = incident;
    this.current_silence = null;
    this._render();
  }

  private addNote(e: CustomEvent): void {
    this.doImpl('/_/add_note', e.detail);
  }

  private delNote(e: CustomEvent): void {
    this.doImpl('/_/del_note', e.detail);
  }

  private addSilenceParam(silence: Silence): void {
    // Don't save silences that are just being created when you add a param.
    if (!silence.key) {
      this.current_silence = silence;
      this._render();
      return;
    }
    this.checked = new Set();
    this.doImpl('/_/save_silence', silence, (json: Silence) => this.silenceAction(json, false));
  }

  private deleteSilenceParam(silence: Silence): void {
    // Don't save silences that are just being created when you delete a param.
    if (!silence.key) {
      this.current_silence = silence;
      this._render();
      return;
    }
    this.checked = new Set();
    this.doImpl('/_/save_silence', silence, (json: Silence) => this.silenceAction(json, false));
  }

  private modifySilenceParam(silence: Silence): void {
    // Don't save silences that are just being created when you modify a param.
    if (!silence.key) {
      this.current_silence = silence;
      this._render();
      return;
    }
    this.checked = new Set();
    this.doImpl('/_/save_silence', silence, (json: Silence) => this.silenceAction(json, false));
  }

  private saveSilence(silence: Silence): void {
    this.checked = new Set();
    this.doImpl('/_/save_silence', silence, (json: Silence) => this.silenceAction(json, true));
  }

  private archiveSilence(silence: Silence): void {
    this.doImpl('/_/archive_silence', silence, (json: Silence) => this.silenceAction(json, true));
  }

  private reactivateSilence(silence: Silence): void {
    this.doImpl('/_/reactivate_silence', silence, (json: Silence) => this.silenceAction(json, false));
  }

  private deleteSilence(silence: Silence): void {
    this.doImpl('/_/del_silence', silence, (json: Silence) => {
      for (let i = 0; i < this.silences.length; i++) {
        if (this.silences[i].key === json.key) {
          this.silences.splice(i, 1);
          this.rhs_state = START;
          break;
        }
      }
    });
  }

  private addSilenceNote(e: CustomEvent): void {
    this.doImpl('/_/add_silence_note', e.detail, (json: Silence) => this.silenceAction(json, false));
  }

  private delSilenceNote(e: CustomEvent): void {
    this.doImpl('/_/del_silence_note', e.detail, (json: Silence) => this.silenceAction(json, false));
  }

  private botChooser(): void {
    this.populateBotsToIncidents(this.incidents);
    ($$('#bot-chooser', this) as BotChooserSk).open(this.bots_to_incidents, this.current_silence!.param_set.bot!).then((bot) => {
      if (!bot) {
        return;
      }
      const bot_incidents = this.bots_to_incidents[bot];
      bot_incidents.forEach((i) => {
        const bot_centric_params: Params = {};
        BOT_CENTRIC_PARAMS.forEach((p) => {
          bot_centric_params[p] = i.params[p];
        });
        paramset.add(this.current_silence!.param_set, bot_centric_params, this.ignored);
      });
      this.modifySilenceParam(this.current_silence!);
    });
  }

  private assign(e: CustomEvent): void {
    const owner = this.selected && (this.selected as Incident).params.owner;
    ($$('#email-chooser', this) as EmailChooserSk).open(this.emails, owner!).then((email) => {
      const detail = {
        key: e.detail.key,
        email: email,
      };
      this.doImpl('/_/assign', detail);
    });
  }

  private flipBotCentricView(): void {
    this.isBotCentricView = !this.isBotCentricView;
    this._render();
  }

  private assignMultiple(): void {
    // See if the selected incidents have a common owner.
    let commonOwner = '';
    for (let i = 0; i < this.incidents.length; i++) {
      if (!this.checked.has(this.incidents[i].key)) {
        // This incident has not been selected.
        continue;
      }
      const incidentOwner = this.incidents[i].params.owner;
      if (incidentOwner) {
        if (commonOwner === '') {
          commonOwner = incidentOwner;
        } else if (commonOwner !== incidentOwner) {
          // The incident owner is different than the common owner found so far.
          // This means there is no common owner;
          commonOwner = '';
          break;
        }
      } else {
        // This incident has no owner so there can be no common owner.
        commonOwner = '';
        break;
      }
    }

    ($$('#email-chooser', this) as EmailChooserSk).open(this.emails, commonOwner).then((email) => {
      const detail = {
        keys: Array.from(this.checked),
        email: email,
      };
      this.doImpl('/_/assign_multiple', detail, (json) => {
        this.incidents = json;
        this.checked = new Set();
        this._render();
      });
    });
  }

  private assignToOwner(e: CustomEvent): void {
    const owner = this.selected && (this.selected as Incident).params.owner;
    const detail = {
      key: e.detail.key,
      email: owner,
    };
    this.doImpl('/_/assign', detail);
  }

  private take(e: CustomEvent): void {
    this.doImpl('/_/take', e.detail);
    // Do not do desktop notification on takes, it is redundant.
    this.incidents_notified[e.detail.key] = true;
  }

  private getStats(): void {
    const detail: StatsRequest = {
      range: this.stats_range,
    };
    this.doImpl('/_/stats', detail, (json: Stat[]) => this.statsAction(json));
  }

  private getAuditLogs(): void {
    this.doImpl('/_/audit_logs', {}, (json: AuditLog[]) => this.auditLogsAction(json));
  }

  private incidentStats(): void {
    const detail: IncidentsInRangeRequest = {
      incident: this.selected as Incident,
      range: this.stats_range,
    };
    this.doImpl('/_/incidents_in_range', detail, (json: Incident[]) => this.incidentStatsAction(json));
  }

  // Actions to take after updating incident stats.
  private incidentStatsAction(json: Incident[]): void {
    this.incident_stats = json;
  }

  // Actions to take after updating Stats.
  private statsAction(json: Stat[]): void {
    this.stats = json;
  }

  // Actions to take after updating Audit Logs.
  private auditLogsAction(json: AuditLog[]): void {
    this.audit_logs = json;
  }

  // Actions to take after updating an Incident.
  private incidentAction(json: Incident): void {
    const incidents = this.incidents;
    for (let i = 0; i < incidents.length; i++) {
      if (incidents[i].key === json.key) {
        incidents[i] = json;
        break;
      }
    }
    this.selected = json;
  }

  // Actions to take after updating a Silence.
  private silenceAction(json: Silence, clear: boolean): void {
    let found = false;
    this.current_silence = json;
    for (let i = 0; i < this.silences.length; i++) {
      if (this.silences[i].key === json.key) {
        this.silences[i] = json;
        found = true;
        break;
      }
    }
    if (!found) {
      this.silences.push(json);
    }
    if (clear) {
      this.rhs_state = START;
    }
  }

  // Common work done for all fetch requests.
  private doImpl(url: string, detail: any, action = (json: any) => this.incidentAction(json)): void {
    this.spinner!.active = true;
    fetch(url, {
      body: JSON.stringify(detail),
      headers: {
        'content-type': 'application/json',
      },
      credentials: 'include',
      method: 'POST',
    }).then(jsonOrThrow).then((json) => {
      action(json);
      this._render();
      this.spinner!.active = false;
    }).catch((msg) => {
      this.spinner!.active = false;
      msg.resp.text().then(errorMessage);
    });
  }

  // Fix-up all the incidents and silences, including re-sorting them.
  private rationalize(): void {
    this.incidents.forEach((incident) => {
      const silenced = this.silences.reduce((isSilenced, silence) => isSilenced
              || (silence.active && paramset.match(silence.param_set, incident.params)), false);
      incident.params.__silence_state = silenced ? 'silenced' : 'active';
    });

    // Sort the incidents, using the following 'sortby' list as tiebreakers.
    const sortby = ['__silence_state', 'assigned_to', 'alertname', 'abbr', 'id'];
    this.incidents.sort((a, b) => {
      // Sort active before inactive.
      if (a.active !== b.active) {
        return a.active ? -1 : 1;
      }
      // Inactive incidents are then sorted by 'lastseen' timestamp.
      if (!a.active) {
        const delta = b.last_seen - a.last_seen;
        if (delta) {
          return delta;
        }
      }
      for (let i = 0; i < sortby.length; i++) {
        const key = sortby[i];
        const left = a.params[key] || '';
        const right = b.params[key] || '';
        const cmp = left.localeCompare(right);
        if (cmp) {
          return cmp;
        }
      }
      return 0;
    });
    this.silences.sort((a, b) => {
      // Sort active before inactive.
      if (a.active !== b.active) {
        return a.active ? -1 : 1;
      }
      return b.updated - a.updated;
    });
  }

  private needsTriaging(incident: Incident, isInfraGardener: boolean): boolean {
    if (incident.active
      && (incident.params.__silence_state !== 'silenced')
      && (
        (isInfraGardener && !incident.params.assigned_to)
        || (incident.params.assigned_to === this.user)
        || (incident.params.owner === this.user
            && !incident.params.assigned_to)
      )
    ) {
      return true;
    }
    return false;
  }

  private requestDesktopNotificationPermission(): void {
    if (Notification && Notification.permission === 'default') {
      Notification.requestPermission();
    }
  }

  private sendDesktopNotification(unNotifiedIncidents: Incident[]): void {
    if (unNotifiedIncidents.length === 0) {
      // Do nothing.
      return;
    }
    let text = '';
    if (unNotifiedIncidents.length === 1) {
      text = `${unNotifiedIncidents[0].params.alertname}\n\n${unNotifiedIncidents[0].params.description}`;
    } else {
      text = `There are ${unNotifiedIncidents.length} alerts assigned to you`;
    }
    const notification = new Notification('am.skia.org notification', {
      icon: '/dist/icon-active.png',
      body: text,
      // 'tag' handles multi-tab scenarios. When multiple tabs are open then
      // only one notification is sent for the same alert.
      tag: `alertManagerNotification${text}`,
    });
    // onclick move focus to the am.skia.org tab and close the notification.
    notification.onclick = () => {
      window.parent.focus();
      window.focus(); // Supports older browsers.
      this.select(unNotifiedIncidents[0]); // Display the 1st incident.
      notification.close();
    };
    setTimeout(notification.close.bind(notification), 10000);
  }

  private _render(): void {
    this.rationalize();
    render(AlertManagerSk.template(this), this, { eventContext: this });
    // Update the icon.
    const isInfraGardener = this.user === this.infra_gardener;
    const numActive = this.incidents.reduce((n, incident) => n += this.needsTriaging(incident, isInfraGardener) ? 1 : 0, 0);

    // Show desktop notifications only if permission was granted and only if
    // silences have been successfully fetched. If silences have not been
    // fetched yet then we might end up notifying on silenced incidents.
    if (Notification.permission === 'granted' && this.silences.length !== 0) {
      const unNotifiedIncidents = this.incidents.filter((i) => !this.incidents_notified[i.key] && this.needsTriaging(i, isInfraGardener));
      this.sendDesktopNotification(unNotifiedIncidents);
      unNotifiedIncidents.forEach((i) => this.incidents_notified[i.key] = true);
    }

    document.title = `${numActive} - AlertManager`;
    if (!this.favicon) {
      return;
    }
    if (numActive > 0) {
      this.favicon.href = '/dist/icon-active.png';
    } else {
      this.favicon.href = '/dist/icon.png';
    }
  }
}

define('alert-manager-sk', AlertManagerSk);
