/**
 * @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/define';
import 'elements-sk/checkbox-sk';
import 'elements-sk/error-toast-sk';
import 'elements-sk/icon/comment-icon-sk';
import 'elements-sk/icon/notifications-icon-sk';
import 'elements-sk/icon/person-icon-sk';
import 'elements-sk/spinner-sk';
import 'elements-sk/styles/buttons';
import 'elements-sk/tabs-panel-sk';
import 'elements-sk/tabs-sk';

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

import { $$ } from 'common-sk/modules/dom';
import { errorMessage } from 'elements-sk/errorMessage';
import { html, render } from 'lit-html';
import { jsonOrThrow } from 'common-sk/modules/jsonOrThrow';
import { stateReflector } from 'common-sk/modules/stateReflector';
import { Login } from '../../../infra-sk/modules/login';

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

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

const MAX_SILENCES_TO_DISPLAY_IN_TAB = 50;

function classOfH2(ele, incident) {
  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 (ele._selected && ele._selected.key === incident.key) {
    ret.push('selected');
  }
  return ret.join(' ');
}

function classOfSilenceH2(ele, silence) {
  const ret = [];
  if (!silence.active) {
    ret.push('inactive');
  }
  if (ele._selected && ele._selected.key === silence.key) {
    ret.push('selected');
  }
  return ret.join(' ');
}

function editIncident(ele) {
  if (ele._selected) {
    return html`<incident-sk .silences=${ele._silences} .state=${ele._selected}
      ></incident-sk>`;
  }
  return '';
}

function editSilence(ele) {
  return html`<silence-sk .state=${ele._current_silence} .incidents=${ele._incidents}
    ></silence-sk>`;
}

function viewStats(ele) {
  return ele._incident_stats.map((i, index) => html`<incident-sk .state=${i} ?minimized params=${index === 0}></incident-sk>`);
}

function rightHandSide(ele) {
  switch (ele._rhs_state) {
    case START:
      return '';
    case INCIDENT:
      return editIncident(ele);
    case EDIT_SILENCE:
      return editSilence(ele);
    case VIEW_STATS:
      return viewStats(ele);
    default:
      return '';
  }
}

function hasNotes(o) {
  return (o.notes && o.notes.length > 0) ? '' : 'invisible';
}

function displayIncident(incident) {
  const ret = [incident.params.alertname];
  const abbr = incident.params.abbr;
  if (abbr) {
    ret.push(` - ${abbr}`);
  }
  let s = ret.join(' ');
  if (s.length > 33) {
    s = `${s.slice(0, 30)}...`;
  }
  return s;
}

function trooper(ele) {
  if (ele._trooper === ele._user) {
    return html`<notifications-icon-sk title='You are the trooper, awesome!'></notifications-icon-sk>`;
  }
  return '';
}

function assignedTo(incident, ele) {
  if (incident.params.assigned_to === ele._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 '';
}

function incidentList(ele, incidents) {
  return incidents.map((i) => html`
    <h2 class=${classOfH2(ele, i)} @click=${() => ele._select(i)}>
    <span class=noselect>
      <checkbox-sk ?checked=${ele._checked.has(i.key)} @change=${ele._check_selected} @click=${ele._clickHandler} id=${i.key}></checkbox-sk>
      ${assignedTo(i, ele)}
      ${displayIncident(i)}
    </span>
    <comment-icon-sk title='This incident has notes.' class=${hasNotes(i)}></comment-icon-sk>
    </h2>
    `);
}

function statsList(ele) {
  return ele._stats.map((stat) => html`<h2 @click=${() => ele._statsClick(stat.incident)}>${displayIncident(stat.incident)} <span>${stat.num}</span></h2>`);
}

function numMatchSilence(ele, s) {
  if (!ele._incidents) {
    return '';
  }
  return ele._incidents.filter(
    (incident) => paramset.match(s.param_set, incident.params) && incident.active,
  ).length;
}

function assignMultiple(ele) {
  return html`<button ?disabled=${ele._checked.size === 0} @click=${ele._assignMultiple}>Assign ${ele._checked.size} alerts</button>`;
}

const template = (ele) => html`
<header>${trooper(ele)}</header>
<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>
  </tabs-sk>
  <tabs-panel-sk>
    <section class=mine>
      ${assignMultiple(ele)}
      ${incidentList(ele, ele._incidents.filter((i) => i.active && i.params.__silence_state !== 'silenced' && (ele._user === ele._trooper || (i.params.assigned_to === ele._user) || (i.params.owner === ele._user && !i.params.assigned_to))))}
    </section>
    <section class=incidents>
      ${assignMultiple(ele)}
      ${incidentList(ele, ele._incidents)}
    </section>
    <section class=silences>
      ${ele._silences.slice(0, MAX_SILENCES_TO_DISPLAY_IN_TAB).map((i) => html`
        <h2 class=${classOfSilenceH2(ele, i)} @click=${() => ele._silenceClick(i)}>
          <span>
            ${displaySilence(i)}
          </span>
          <span>
            <span title='Expires in'>${expiresIn(i)}</span>
            <comment-icon-sk title='This silence has notes.' class=${hasNotes(i)}></comment-icon-sk>
            <span title='The number of active alerts that match this silence.'>${numMatchSilence(ele, i)}</span>
          </span>
        </h2>`)}
    </section>
    <section class=stats>
      ${statsList(ele)}
    </section>
  </tabs-panel-sk>
</section>
<section class=edit>
  ${rightHandSide(ele)}
</section>
<footer>
  <spinner-sk id=busy></spinner-sk>
  <email-chooser-sk id=chooser></email-chooser-sk>
  <error-toast-sk></error-toast-sk>
<footer>
`;

function findParent(ele, tagName) {
  while (ele && (ele.tagName !== tagName)) {
    ele = ele.parentElement;
  }
  return ele;
}

define('alert-manager-sk', class extends HTMLElement {
  constructor() {
    super();
    this._incidents = []; // All active incidents.
    this._silences = []; // All active silences.
    this._stats = []; // Last requested stats.
    this._stats_range = '1w';
    this._incident_stats = []; // The incidents for a given stat.
    this._rhs_state = START; // One of START, INCIDENT, or EDIT_SILENCE.
    this._selected = null; // The selected incident, i.e. you clicked on the name.
    this._checked = new Set(); // Checked incidents, i.e. you clicked the checkbox.
    this._current_silence = null; // A silence under construction.
    // Params to ignore when constructing silences.
    this._ignored = ['__silence_state', 'description', 'id', 'swarming', 'assigned_to',
      'kubernetes_pod_name', 'instance', 'pod_template_hash', 'abbr_owner_regex',
      'controller_revision_hash'];
    this._shift_pressed_during_click = false; // If the shift key was held down during the mouse click.
    this._last_checked_incident = null; // Keeps track of the last checked incident. Used for multi-selecting incidents with shift.
    this._incidents_notified = {}; // Keeps track of all incidents that were notified via desktop notifications.
    this._user = 'barney@example.org';
    this._trooper = '';
    this._state = {
      tab: 0, // The selected tab.
    };
    fetch('https://tree-status.skia.org/current-trooper', { mode: 'cors' }).then(jsonOrThrow).then((json) => {
      this._trooper = json.username;
      this._render();
    });
    Login.then((loginstatus) => {
      this._user = loginstatus.Email;
      this._render();
    });
  }

  connectedCallback() {
    this._requestDesktopNotificationPermission();

    this.addEventListener('save-silence', (e) => this._saveSilence(e.detail.silence));
    this.addEventListener('archive-silence', (e) => this._archiveSilence(e.detail.silence));
    this.addEventListener('reactivate-silence', (e) => this._reactivateSilence(e.detail.silence));
    this.addEventListener('delete-silence', (e) => this._deleteSilence(e.detail.silence));
    this.addEventListener('add-silence-note', (e) => this._addSilenceNote(e));
    this.addEventListener('del-silence-note', (e) => this._delSilenceNote(e));
    this.addEventListener('add-silence-param', (e) => this._addSilenceParam(e.detail.silence));
    this.addEventListener('delete-silence-param', (e) => this._deleteSilenceParam(e.detail.silence));
    this.addEventListener('modify-silence-param', (e) => this._modifySilenceParam(e.detail.silence));
    this.addEventListener('add-note', (e) => this._addNote(e));
    this.addEventListener('del-note', (e) => this._delNote(e));
    this.addEventListener('take', (e) => this._take(e));
    this.addEventListener('assign', (e) => this._assign(e));
    this.addEventListener('assign-to-owner', (e) => this._assignToOwner(e));

    this._stateHasChanged = stateReflector(
      () => this._state,
      (state) => {
        this._state = state;
        this._render();
      },
    );

    this._render();
    this._busy = $$('#busy', this);
    this._favicon = $$('#favicon');

    this._busy.active = true;
    this._poll(true);
  }

  _poll(stopSpinner) {
    const incidents = fetch('/_/incidents', {
      credentials: 'include',
    }).then(jsonOrThrow).then((json) => {
      this._incidents = json;
    });

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

    const emails = fetch('/_/emails', {
      credentials: 'include',
    }).then(jsonOrThrow).then((json) => {
      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._busy.active = false;
      }
      window.setTimeout(() => this._poll(), 10000);
    });
  }

  _tabSwitch(e) {
    this._state.tab = e.detail.index;
    this._stateHasChanged();

    // 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) => {
        this._selected = null;
        this._current_silence = json;
        this._rhs_state = EDIT_SILENCE;
        this._render();
      }).catch(errorMessage);
    } else {
      this._rhs_state = START;
      this._render();
    }
  }

  _clickHandler(e) {
    this._shift_pressed_during_click = e.shiftKey;
    e.stopPropagation();
  }

  _silenceClick(silence) {
    this._current_silence = JSON.parse(JSON.stringify(silence));
    this._selected = silence;
    this._rhs_state = EDIT_SILENCE;
    this._render();
  }

  _statsClick(incident) {
    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.
  _check_selected_impl(key, isChecked) {
    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);
        }
      });
    }

    this._rhs_state = EDIT_SILENCE;
    this._render();
  }

  _check_selected(e) {
    const checkbox = findParent(e.target, 'CHECKBOX-SK');
    if (!this._checked.size) {
      // Request a new silence.
      fetch('/_/new_silence', {
        credentials: 'include',
      }).then(jsonOrThrow).then((json) => {
        this._selected = null;
        this._current_silence = json;
        this._check_selected_impl(checkbox.id, checkbox._input.checked);
      }).catch(errorMessage);
    } else if (this._shift_pressed_during_click && this._last_checked_incident) {
      let foundStart = false;
      let foundEnd = false;
      const incidents_to_check = [];
      this._incidents.some((i) => {
        if (i.key === this._last_checked_incident || i.key === checkbox.id) {
          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_to_check.push(i.key);
        }
        return foundEnd;
      });

      if (foundStart && foundEnd) {
        incidents_to_check.forEach((key) => {
          this._check_selected_impl(key, true);
        });
      } else {
        // Could not find start and/or end incident. Only check the last
        // clicked.
        this._check_selected_impl(checkbox.id, checkbox._input.checked);
      }
    } else {
      this._check_selected_impl(checkbox.id, checkbox._input.checked);
    }
  }

  _select(incident) {
    this._rhs_state = INCIDENT;
    this._checked = new Set();
    this._selected = incident;
    this._current_silence = null;
    this._render();
  }

  _addNote(e) {
    this._doImpl('/_/add_note', e.detail);
  }

  _delNote(e) {
    this._doImpl('/_/del_note', e.detail);
  }

  _addSilenceParam(silence) {
    // 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) => this._silenceAction(json, false));
  }

  _deleteSilenceParam(silence) {
    // 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) => this._silenceAction(json, false));
  }

  _modifySilenceParam(silence) {
    // 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) => this._silenceAction(json, false));
  }

  _saveSilence(silence) {
    this._checked = new Set();
    this._doImpl('/_/save_silence', silence, (json) => this._silenceAction(json, true));
  }

  _archiveSilence(silence) {
    this._doImpl('/_/archive_silence', silence, (json) => this._silenceAction(json, true));
  }

  _reactivateSilence(silence) {
    this._doImpl('/_/reactivate_silence', silence, (json) => this._silenceAction(json, false));
  }

  _deleteSilence(silence) {
    this._doImpl('/_/del_silence', silence, (json) => {
      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;
        }
      }
    });
  }

  _addSilenceNote(e) {
    this._doImpl('/_/add_silence_note', e.detail, (json) => this._silenceAction(json, false));
  }

  _delSilenceNote(e) {
    this._doImpl('/_/del_silence_note', e.detail, (json) => this._silenceAction(json, false));
  }

  _assign(e) {
    const owner = this._selected && this._selected.params.owner;
    $$('#chooser', this).open(this._emails, owner).then((email) => {
      const detail = {
        key: e.detail.key,
        email: email,
      };
      this._doImpl('/_/assign', detail);
    });
  }

  _assignMultiple() {
    const owner = (this._selected && this._selected.params.owner) || '';
    $$('#chooser', this).open(this._emails, owner).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();
      });
    });
  }

  _assignToOwner(e) {
    const owner = this._selected && this._selected.params.owner;
    const detail = {
      key: e.detail.key,
      email: owner,
    };
    this._doImpl('/_/assign', detail);
  }

  _take(e) {
    this._doImpl('/_/take', e.detail);
    // Do not do desktop notification on takes, it is redundant.
    this._incidents_notified[e.detail.key] = true;
  }

  _getStats() {
    const detail = {
      range: this._stats_range,
    };
    this._doImpl('/_/stats', detail, (json) => this._statsAction(json));
  }

  _incidentStats() {
    const detail = {
      incident: this._selected,
      range: this._stats_range,
    };
    this._doImpl('/_/incidents_in_range', detail, (json) => this._incidentStatsAction(json));
  }

  // Actions to take after updating incident stats.
  _incidentStatsAction(json) {
    this._incident_stats = json;
  }

  // Actions to take after updating Stats.
  _statsAction(json) {
    this._stats = json;
  }

  // Actions to take after updating an Incident.
  _incidentAction(json) {
    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.
  _silenceAction(json, clear) {
    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.
  _doImpl(url, detail, action = (json) => this._incidentAction(json)) {
    this._busy.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._busy.active = false;
    }).catch((msg) => {
      this._busy.active = false;
      msg.resp.text().then(errorMessage);
    });
  }

  // Fix-up all the incidents and silences, including re-sorting them.
  _rationalize() {
    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;
    });
  }

  _needsTriaging(incident, isTrooper) {
    if (incident.active
      && (incident.params.__silence_state !== 'silenced')
      && (
        (isTrooper && !incident.params.assigned_to)
        || (incident.params.assigned_to === this._user)
        || (incident.params.owner === this._user
            && !incident.params.assigned_to)
      )
    ) {
      return true;
    }
    return false;
  }

  _requestDesktopNotificationPermission() {
    if (Notification && Notification.permission === 'default') {
      Notification.requestPermission((permission) => {
        if (!('permission' in Notification)) {
          Notification.permission = permission;
        }
      });
    }
  }

  _sendDesktopNotification(unNotifiedIncidents) {
    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: '/static/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.
    const that = this;
    notification.onclick = function() {
      window.parent.focus();
      window.focus(); // Supports older browsers.
      that._select(unNotifiedIncidents[0]); // Display the 1st incident.
      this.close();
    };
    setTimeout(notification.close.bind(notification), 10000);
  }

  _render() {
    this._rationalize();
    render(template(this), this, { eventContext: this });
    // Update the icon.
    const isTrooper = this._user === this._trooper;
    const numActive = this._incidents.reduce((n, incident) => n += this._needsTriaging(incident, isTrooper) ? 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, isTrooper));
      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 = '/static/icon-active.png';
    } else {
      this._favicon.href = '/static/icon.png';
    }
  }
});
