/**
 * @module modules/machine-server
 * @description <h2><code>machine-server</code></h2>
 *
 * The main machine server landing page.
 *
 * Uses local storage to persist the user's choice of auto-refresh.
 *
 * @attr waiting - If present then display the waiting cursor.
 */
import { html, TemplateResult } from 'lit-html';

import { jsonOrThrow } from '../../../infra-sk/modules/jsonOrThrow';
import { diffDate, strDuration } from '../../../infra-sk/modules/human';
import { $$ } from '../../../infra-sk/modules/dom';
import { errorMessage } from '../../../elements-sk/modules/errorMessage';
import {
  Annotation,
  AttachedDevice,
  Description,
  SetAttachedDevice,
  SetNoteRequest,
  SupplyChromeOSRequest,
} from '../json';

import '../../../infra-sk/modules/theme-chooser-sk/theme-chooser-sk';
import '../../../infra-sk/modules/clipboard-sk';
import '../../../elements-sk/modules/error-toast-sk/index';
import '../../../elements-sk/modules/icons/block-icon-sk';
import '../../../elements-sk/modules/icons/cached-icon-sk';
import '../../../elements-sk/modules/icons/delete-icon-sk';
import '../../../elements-sk/modules/icons/edit-icon-sk';
import '../../../elements-sk/modules/icons/launch-icon-sk';
import '../../../elements-sk/modules/icons/power-settings-new-icon-sk';
import '../../../elements-sk/modules/icons/warning-icon-sk';
import '../../../elements-sk/modules/spinner-sk';
import '../../../elements-sk/modules/icons/sort-icon-sk';
import '../../../elements-sk/modules/icons/arrow-drop-down-icon-sk';
import '../../../elements-sk/modules/icons/arrow-drop-up-icon-sk';
import '../../../elements-sk/modules/icons/clear-all-icon-sk';
import '../../../elements-sk/modules/icons/content-copy-icon-sk';
import { NoteEditorSk } from '../note-editor-sk/note-editor-sk';
import '../auto-refresh-sk';
import '../device-editor-sk';
import '../note-editor-sk';
import { DEVICE_ALIASES } from '../../../modules/devices/devices';
import {
  ClearDeviceEvent,
  DeviceEditorSk,
  UpdateDimensionsDetails,
  UpdateDimensionsEvent,
} from '../device-editor-sk/device-editor-sk';
import { compareFunc, SortHistory, up } from '../sort';
import { ElementSk } from '../../../infra-sk/modules/ElementSk/ElementSk';
import { FilterArray } from '../filter-array';
import {
  ColumnOrder,
  ColumnTitles,
  MachineTableColumnsDialogSk,
} from '../machine-table-columns-dialog-sk/machine-table-columns-dialog-sk';
import '../machine-table-columns-dialog-sk/machine-table-columns-dialog-sk';

export type WaitCursor = 'DoNotShowWaitCursor' | 'ShowWaitCursor';

/**
 * Updates should arrive every 30 seconds, so we allow up to 2x that for lag
 * before showing it as an error.
 * */
export const MAX_LAST_UPDATED_ACCEPTABLE_MS = 60 * 1000;

/**
 * Devices should be restarted every 24 hours, with an hour added if they are
 * running a test.
 */
export const MAX_UPTIME_ACCEPTABLE_S = 60 * 60 * 25;

export const MachineTableSkSortChangeEventName: string =
  'machine-table-sort-change';

/** The event detail is the sort history of the table encoded as a string. */
export type MachineTableSkChangeEventDetail = string;

const attachedDeviceDisplayName: Record<string, AttachedDevice> = {
  '-': 'nodevice',
  Android: 'adb',
  iOS: 'ios',
  SSH: 'ssh',
};

/** attachedDeviceDisplayName keys sorted by display name. */
const attachedDeviceDisplayNamesOrder: string[] = Object.keys(
  attachedDeviceDisplayName
).sort();

/** sortBooleans is a utility function for sorting booleans, where true comes
 * before false. */
const sortBooleans = (a: boolean, b: boolean): number => {
  if (a === b) {
    return 0;
  }
  if (a) {
    return 1;
  }
  return -1;
};

/** checkResponse throws an error with the response body text if the response
 * was not 'ok'. */
const checkResponse = async (resp: Response): Promise<void> => {
  if (!resp.ok) {
    throw await resp.text();
  }
};

// Sort functions for different clumns, i.e. values in Description.

// Mode no longer exists, so this is a no-op.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const sortByMode = (a: Description, b: Description): number =>
  a.MaintenanceMode.localeCompare(b.MaintenanceMode);

export const sortByAttachedDevice = (a: Description, b: Description): number =>
  a.AttachedDevice.localeCompare(b.AttachedDevice);

export const sortByAnnotation = (a: Description, b: Description): number =>
  a.Annotation.Message.localeCompare(b.Annotation.Message);

export const sortByNote = (a: Description, b: Description): number =>
  a.Note.Message.localeCompare(b.Note.Message);

export const sortByVersion = (a: Description, b: Description): number =>
  a.Version.localeCompare(b.Version);

export const sortByPowerCycle = (a: Description, b: Description): number => {
  const powerCycleSort = sortBooleans(a.PowerCycle, b.PowerCycle);
  if (powerCycleSort === 0) {
    return a.PowerCycleState.localeCompare(b.PowerCycleState);
  }
  return powerCycleSort;
};

export const sortByLastUpated = (a: Description, b: Description): number =>
  a.LastUpdated.localeCompare(b.LastUpdated);

export const sortByBattery = (a: Description, b: Description): number =>
  a.Battery - b.Battery;

export const sortByRunningSwarmingTask = (
  a: Description,
  b: Description
): number => sortBooleans(a.RunningSwarmingTask, b.RunningSwarmingTask);

export const sortByLaunchedSwarming = (
  a: Description,
  b: Description
): number => sortBooleans(a.LaunchedSwarming, b.LaunchedSwarming);

export const sortByDeviceUptime = (a: Description, b: Description): number =>
  a.DeviceUptime - b.DeviceUptime;

export const sortByDevice = (a: Description, b: Description): number =>
  pretty_device_name_as_string(a).localeCompare(
    pretty_device_name_as_string(b)
  );

export const sortByQuarantined = (a: Description, b: Description): number => {
  const qa = a.Dimensions!.quarantined?.join('') || '';
  const qb = b.Dimensions!.quarantined?.join('') || '';
  return qa.localeCompare(qb);
};

export const sortByMachineID = (a: Description, b: Description): number => {
  const qa = a.Dimensions!.id?.join('') || '';
  const qb = b.Dimensions!.id?.join('') || '';
  return qa.localeCompare(qb);
};

export const sortByRecovering = (a: Description, b: Description): number =>
  a.Recovering.localeCompare(b.Recovering);

export const sortByIsQuarantined = (a: Description, b: Description): number =>
  sortBooleans(a.IsQuarantined, b.IsQuarantined);

// Do not change the location of these functions, i.e. their index, as that would
// change the meaning of URLs already in the wild. Always add new sort functions
// to the end of the list, and if a sort function is no-longer used replace it with
// a no-op function, e.g. (a: Description, b: Description): number => 0.
const sortFunctionsByColumn: compareFunc<Description>[] = [
  sortByMachineID,
  sortByAttachedDevice,
  sortByDevice,
  sortByMode,
  sortByPowerCycle,
  sortByQuarantined,
  sortByRunningSwarmingTask,
  sortByBattery,
  sortByLastUpated,
  sortByDeviceUptime,
  sortByLaunchedSwarming,
  sortByNote,
  sortByAnnotation,
  sortByVersion,
  sortByRecovering,
  sortByIsQuarantined,
];

const temps = (machine: Description): TemplateResult => {
  const temperatures = machine.Temperature;
  if (!temperatures) {
    return html``;
  }
  const values = Object.values(temperatures);
  if (!values.length) {
    return html``;
  }
  let total = 0;
  values.forEach((x) => {
    total += x;
  });
  const ave = total / values.length;
  return html`
    <details>
      <summary>Avg: ${ave.toFixed(1)}</summary>
      <table>
        ${Object.entries(temperatures).map(
          (pair) => html`
            <tr>
              <td>${pair[0]}</td>
              <td>${pair[1]}</td>
            </tr>
          `
        )}
      </table>
    </details>
  `;
};

const lastSeen = (machine: Description): TemplateResult =>
  html`${diffDate(machine.LastUpdated)}`;

const isRunning = (machine: Description): TemplateResult =>
  machine.RunningSwarmingTask
    ? html` <cached-icon-sk title="Running"></cached-icon-sk> `
    : html``;

const asList = (arr: string[] | null) => (arr === null ? '' : arr.join(' | '));

const launchedSwarming = (machine: Description): TemplateResult => {
  if (!machine.LaunchedSwarming) {
    return html``;
  }
  return html`
    <launch-icon-sk
      title="Swarming was launched by test_machine_monitor."
    ></launch-icon-sk>
  `;
};

const annotation = (ann: Annotation): TemplateResult => {
  if (!ann?.Message) {
    return html``;
  }
  return html` ${ann.User} (${diffDate(ann.Timestamp)}) - ${ann.Message} `;
};

const imageVersion = (machine: Description): TemplateResult => {
  if (machine.Version) {
    return html`${machine.Version}`;
  }
  return html`(missing)`;
};

/** Displays the device uptime, truncated to the minute. */
const deviceUptime = (machine: Description): TemplateResult => html`
  ${strDuration(machine.DeviceUptime - (machine.DeviceUptime % 60))}
`;

/** Returns the CSS class that should decorate the LastUpdated value. */
export const outOfSpecIfTooOld = (machine: Description): string => {
  const lastUpdated = machine.LastUpdated;
  const diff = Date.now() - Date.parse(lastUpdated);
  return diff > MAX_LAST_UPDATED_ACCEPTABLE_MS ? 'outOfSpec' : '';
};

/** Returns the CSS class that should decorate the Uptime value. */
export const uptimeOutOfSpecIfTooOld = (machine: Description): string =>
  machine.DeviceUptime > MAX_UPTIME_ACCEPTABLE_S ? 'outOfSpec' : '';

// Returns the device_type separated with vertical bars and a trailing device
// alias if that name is known.
const pretty_device_name = (machine: Description): TemplateResult =>
  html`${pretty_device_name_as_string(machine)}`;

// Returns the device_type separated with vertical bars and a trailing device
// alias if that name is known.
export const pretty_device_name_as_string = (machine: Description): string => {
  const devices = machine.Dimensions?.device_type;

  if (!devices) {
    return '';
  }
  let alias = '';
  for (let i = 0; i < devices.length; i++) {
    const found = DEVICE_ALIASES[devices[i]];
    if (found) {
      alias = `(${found})`;
    }
  }
  return `${devices.join(' | ')} ${alias}`;
};

const quarantined = (machine: Description): TemplateResult =>
  html`${machine.Dimensions!.quarantined}`;

const battery = (machine: Description): TemplateResult =>
  html`${machine.Battery}`;

// Column stores information about a single column in the table.
class Column {
  name: string;

  row: (machine: Description) => TemplateResult;

  compare: compareFunc<Description> | null;

  className: ((machine: Description) => string) | null;

  computedClipValue: (() => Promise<string>) | null;

  /** constructor
   *
   * name - The displayed name of the column.
   * row - A function that emits the `td` HTML for each row in this column,
   * compare - An optional comparison function for sorting based on the values in this column.
   * className - An optional function to compute the class name to apply to each row's `td`.
   * computedClipValue - An optional function that computes a value to send to the clipboard. A non-null
   *    value will cause a clipboard-sk element to be added to the header.
   */
  constructor(
    name: string,
    row: (machine: Description) => TemplateResult,
    compare: compareFunc<Description> | null,
    className: ((machine: Description) => string) | null = null,
    computedClipValue: (() => Promise<string>) | null = null
  ) {
    this.name = name;
    this.row = row;
    this.compare = compare;
    this.className = className;
    this.computedClipValue = computedClipValue;
  }

  // eslint-disable-next-line no-use-before-define
  header(ele: MachinesTableSk): TemplateResult {
    return html`<th>${
      this.name
    }${this.optionalClipboard()}${this.optionalSortArrow(ele)}</div></th>`;
  }

  // eslint-disable-next-line no-use-before-define
  optionalSortArrow(ele: MachinesTableSk): TemplateResult {
    if (this.compare === null) {
      return html``;
    }
    return html`&nbsp;${ele.sortArrow(this.compare)}`;
  }

  optionalClipboard(): TemplateResult {
    if (this.computedClipValue === null) {
      return html``;
    }
    return html`&nbsp;<clipboard-sk
        .calculatedValue=${this.computedClipValue}
      ></clipboard-sk>`;
  }

  rowValue(machine: Description): TemplateResult {
    if (this.className === null) {
      return html`<td>${this.row(machine)}</td>`;
    }
    return html`<td class=${this.className(machine)}>${this.row(machine)}</td>`;
  }
}

/**
 * The URL path from which to fetch the JSON representation of the latest
 * list items
 */
const fetchPath = '/_/machines';

export class MachinesTableSk extends ElementSk {
  private noteEditor: NoteEditorSk | null = null;

  deviceEditor: DeviceEditorSk | null = null;

  private sortHistory: SortHistory<Description> = new SortHistory(
    sortFunctionsByColumn
  );

  private filterer: FilterArray<Description> = new FilterArray();

  private hiddenColumns: ColumnTitles[] = [
    'Launched Swarming',
    'Version',
    'Annotation',
  ];

  private hiddenColumnsDialog: MachineTableColumnsDialogSk | null = null;

  private columns: Record<ColumnTitles, Column> | null = null;

  private static template = (ele: MachinesTableSk): TemplateResult => html`
    <table>
      <thead>
        <tr>
          ${ele.tableHeaders()}
        </tr>
      </thead>
      <tbody>
        ${ele.tableRows()}
      </tbody>
    </table>
    ${ele.moreTemplate()}
  `;

  constructor() {
    super(MachinesTableSk.template);
    this.classList.add('defaultLiveTableSkStyling');

    this.columns = {
      Machine: new Column(
        'Machine',
        this.machineLink.bind(this),
        sortByMachineID,
        null,
        this.allDisplayedMachineIDs.bind(this)
      ),
      Attached: new Column(
        'Attached',
        this.attachedDevice.bind(this),
        sortByAttachedDevice
      ),
      Device: new Column('Device', pretty_device_name, sortByDevice),
      Mode: new Column('Mode', this.toggleModeElement.bind(this), sortByMode),
      Recovering: new Column(
        'Recovering',
        this.recovering.bind(this),
        sortByRecovering
      ),
      Power: new Column(
        'Power',
        this.powerCycle.bind(this),
        sortByPowerCycle,
        () => 'powercycle'
      ),
      Details: new Column('Details', this.editDeviceIcon.bind(this), null),
      Quarantined: new Column('Quarantined', quarantined, sortByQuarantined),
      'Clear Quarantine': new Column(
        'Clear Quarantine',
        this.clearQuarantine.bind(this),
        sortByIsQuarantined
      ),
      Task: new Column('Task', isRunning, sortByRunningSwarmingTask),
      Battery: new Column('Battery', battery, sortByBattery),
      Temperature: new Column('Temperature', temps, null),
      'Last Seen': new Column(
        'Last Seen',
        lastSeen,
        sortByLastUpated,
        outOfSpecIfTooOld
      ),
      Uptime: new Column(
        'Uptime',
        deviceUptime,
        sortByDeviceUptime,
        uptimeOutOfSpecIfTooOld
      ),
      Dimensions: new Column('Dimensions', this.dimensions.bind(this), null),
      'Launched Swarming': new Column(
        'Launched Swarming',
        launchedSwarming,
        sortByLaunchedSwarming
      ),
      Note: new Column('Note', this.note.bind(this), sortByNote),
      Annotation: new Column(
        'Annotation',
        (machine: Description) => annotation(machine.Annotation),
        sortByAnnotation
      ),
      Version: new Column('Version', imageVersion, sortByVersion),
      Delete: new Column('Delete', this.deleteMachine.bind(this), null),
    };
  }

  async allDisplayedMachineIDs(): Promise<string> {
    return this.orderedFilteredRows()
      .map((d: Description) => d.Dimensions!.id![0])
      .join('\n');
  }

  private orderedFilteredRows(): Description[] {
    const ret = this.filterer.matchingValues();
    ret.sort(this.sortHistory.compare.bind(this.sortHistory));
    return ret;
  }

  private tableRows(): TemplateResult[] {
    const ret: TemplateResult[] = [];
    this.orderedFilteredRows().forEach((item) =>
      ret.push(
        html`<tr>
          ${this.tableRow(item)}
        </tr>`
      )
    );
    return ret;
  }

  /**
   * Show and hide rows to reflect a change in the filtration string.
   */
  filterChanged(value: string): void {
    this.filterer.filterChanged(value);
    this._render();
  }

  restoreSortState(value: string): void {
    this.sortHistory.decode(value);
  }

  restoreHiddenColumns(value: ColumnTitles[]): void {
    this.hiddenColumns = value;
    this._render();
  }

  // eslint-disable-next-line no-use-before-define
  toggleModeElement(machine: Description): TemplateResult {
    return html`
      <button
        class="mode"
        @click=${() => this.toggleMode(machine.Dimensions!.id![0])}
        title="${machine.MaintenanceMode || 'Put machine in maintenance mode'}"
      >
        ${machine.MaintenanceMode === '' ? 'available' : 'maintenance'}
      </button>
    `;
  }

  recovering(machine: Description): TemplateResult {
    return html`${machine.Recovering}`;
  }

  powerCycle(machine: Description): TemplateResult {
    return html`
      <power-settings-new-icon-sk
        title="Powercycle the host"
        class="clickable"
        @click=${() => this.togglePowerCycle(machine.Dimensions!.id![0])}
        ?hidden=${machine.PowerCycleState !== 'available'}
      ></power-settings-new-icon-sk>
      <warning-icon-sk
        ?hidden=${machine.PowerCycleState !== 'in_error'}
        title="Controller failed to connect."
      ></warning-icon-sk>
      <spinner-sk ?active=${machine.PowerCycle}></spinner-sk>
    `;
  }

  clearQuarantine(machine: Description): TemplateResult {
    return html`
      <block-icon-sk
        title="Clear the quarantine"
        class="clickable"
        @click=${() => this.clearQuarantineAction(machine.Dimensions!.id![0])}
        ?hidden=${!machine.IsQuarantined}
      ></block-icon-sk>
    `;
  }

  editDeviceIcon(machine: Description): TemplateResult {
    return machine.RunningSwarmingTask || machine.AttachedDevice !== 'ssh'
      ? html``
      : html`
          <edit-icon-sk
            title="Edit/clear the dimensions for the bot"
            class="edit_device"
            @click=${() =>
              this.deviceEditor!.show(machine.Dimensions, machine.SSHUserIP)}
          ></edit-icon-sk>
        `;
  }

  note(machine: Description): TemplateResult {
    return html`
      <edit-icon-sk
        class="edit_note clickable"
        @click=${() => this.editNote(machine.Dimensions!.id![0], machine)}
      ></edit-icon-sk
      >${annotation(machine.Note)}
    `;
  }

  deleteMachine(machine: Description): TemplateResult {
    return html`
      <delete-icon-sk
        title="Remove the machine from the database."
        class="clickable"
        @click=${() => this.deleteDevice(machine.Dimensions!.id![0])}
      ></delete-icon-sk>
    `;
  }

  dimensions(machine: Description): TemplateResult {
    if (!machine.Dimensions) {
      return html`<div>Unknown</div>`;
    }
    return html`
      <div class="dimensions">
        <clear-all-icon-sk
          title="Clear all dimensions from the datastore"
          @click=${() => this.clearDeviceByID(machine.Dimensions!.id![0])}
        >
        </clear-all-icon-sk>
        <details class="dimensions">
          <summary>Dimensions</summary>
          <table>
            ${Object.entries(machine.Dimensions).map(
              (pair) => html`
                <tr>
                  <td>${pair[0]}</td>
                  <td>${asList(pair[1])}</td>
                </tr>
              `
            )}
          </table>
        </details>
      </div>
    `;
  }

  /**
   * Fetch the latest list from the server, and update the page to reflect it.
   *
   * @param showWaitCursor Whether the mouse pointer should be changed to a
   *   spinner while we wait for the fetch
   */
  async update(
    waitCursorPolicy: WaitCursor = 'DoNotShowWaitCursor'
  ): Promise<void> {
    if (waitCursorPolicy === 'ShowWaitCursor') {
      this.setAttribute('waiting', '');
    }

    try {
      const resp = await fetch(fetchPath);
      await checkResponse(resp);
      const json = await jsonOrThrow(resp);
      if (waitCursorPolicy === 'ShowWaitCursor') {
        this.removeAttribute('waiting');
      }
      this.filterer.updateArray(json);
      this._render();
    } catch (error: any) {
      this.onError(error);
    }
  }

  onError(msg: { message: string } | string): void {
    this.removeAttribute('waiting');
    errorMessage(msg);
  }

  tableHeaders(): TemplateResult[] {
    return ColumnOrder.filter((name) => !this.hiddenColumns.includes(name)).map(
      (columnName) => this.columns![columnName].header(this)
    );
  }

  tableRow(machine: Description): TemplateResult[] {
    if (!machine.Dimensions || !machine.Dimensions.id) {
      return [];
    }
    return ColumnOrder.filter((name) => !this.hiddenColumns.includes(name)).map(
      (columnName) => this.columns![columnName].rowValue(machine)
    );
  }

  private moreTemplate(): TemplateResult {
    return html`
      <note-editor-sk></note-editor-sk>
      <device-editor-sk></device-editor-sk>
      <machine-table-columns-dialog-sk></machine-table-columns-dialog-sk>
    `;
  }

  private attachedDeviceOptions(machine: Description): TemplateResult[] {
    return attachedDeviceDisplayNamesOrder.map(
      (key: string) => html` <option
        value=${attachedDeviceDisplayName[key]}
        ?selected=${attachedDeviceDisplayName[key] === machine.AttachedDevice}
      >
        ${key}
      </option>`
    );
  }

  private machineLink(machine: Description): TemplateResult {
    return html`
      <a
        href="https://chromium-swarm.appspot.com/bot?id=${machine.Dimensions!
          .id}"
      >
        ${machine.Dimensions!.id}
      </a>
      <clipboard-sk value="${machine.Dimensions!.id![0]}"></clipboard-sk>
    `;
  }

  private attachedDevice(machine: Description): TemplateResult {
    return html` <select
      @input=${(e: InputEvent) =>
        this.attachedDeviceChanged(e, machine.Dimensions!.id![0])}
    >
      ${this.attachedDeviceOptions(machine)}
    </select>`;
  }

  sortArrow(fn: compareFunc<Description>): TemplateResult {
    const column = sortFunctionsByColumn.indexOf(fn);
    if (column === -1) {
      errorMessage(`Invalid compareFunc: ${fn.name}`);
    }
    const firstSortSelection = this.sortHistory!.history[0];

    if (column === firstSortSelection.column) {
      if (firstSortSelection.dir === up) {
        return html`<arrow-drop-up-icon-sk
          title="Change sort order to descending."
          @click=${() => this.changeSort(column)}
        ></arrow-drop-up-icon-sk>`;
      }
      return html`<arrow-drop-down-icon-sk
        title="Change sort order to ascending."
        @click=${() => this.changeSort(column)}
      ></arrow-drop-down-icon-sk>`;
    }
    return html`<sort-icon-sk
      title="Sort this column."
      @click=${() => this.changeSort(column)}
    ></sort-icon-sk>`;
  }

  private changeSort(column: number) {
    this.sortHistory!.selectColumnToSortOn(column);

    this.dispatchEvent(
      new CustomEvent<MachineTableSkChangeEventDetail>(
        MachineTableSkSortChangeEventName,
        { detail: this.sortHistory!.encode(), bubbles: true }
      )
    );
    this._render();
  }

  connectedCallback(): void {
    super.connectedCallback();
    this._render();
    this.noteEditor = $$<NoteEditorSk>('note-editor-sk', this);
    this.deviceEditor = $$<DeviceEditorSk>('device-editor-sk', this);
    this.hiddenColumnsDialog = $$<MachineTableColumnsDialogSk>(
      'machine-table-columns-dialog-sk',
      this
    );

    this.addEventListener(ClearDeviceEvent, this.clearDevice);
    this.addEventListener(UpdateDimensionsEvent, this.updateDimensions);
  }

  disconnectedCallback(): void {
    super.disconnectedCallback();

    this.removeEventListener(ClearDeviceEvent, this.clearDevice);
    this.removeEventListener(UpdateDimensionsEvent, this.updateDimensions);
  }

  /** Performs the fetch and if successful updates the UI. */
  async fetchCheckAndUpdate(input: string, init?: RequestInit): Promise<void> {
    try {
      this.setAttribute('waiting', '');
      const resp = await fetch(input, init);
      await checkResponse(resp);
      await this.update('ShowWaitCursor');
    } catch (error) {
      this.onError(error as string);
    } finally {
      this.removeAttribute('waiting');
    }
  }

  async toggleUpdate(id: string): Promise<void> {
    await this.fetchCheckAndUpdate(`/_/machine/toggle_update/${id}`);
  }

  async attachedDeviceChanged(e: InputEvent, id: string): Promise<void> {
    const sel = e.target as HTMLSelectElement;
    const request: SetAttachedDevice = {
      AttachedDevice: sel.selectedOptions[0].value as AttachedDevice,
    };
    await this.fetchCheckAndUpdate(`/_/machine/set_attached_device/${id}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(request),
    });
  }

  async toggleMode(id: string): Promise<void> {
    await this.fetchCheckAndUpdate(`/_/machine/toggle_mode/${id}`, {
      method: 'POST',
    });
  }

  async editNote(id: string, machine: Description): Promise<void> {
    const editedAnnotation = await this.noteEditor!.edit(machine.Note);
    if (!editedAnnotation) {
      return;
    }
    const request: SetNoteRequest = editedAnnotation;
    this.setAttribute('waiting', '');
    await this.fetchCheckAndUpdate(`/_/machine/set_note/${id}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(request),
    });
  }

  async editHiddenColumns(): Promise<ColumnTitles[]> {
    const newHiddenColumns = await this.hiddenColumnsDialog!.edit(
      this.hiddenColumns
    );
    if (!newHiddenColumns) {
      return this.hiddenColumns;
    }
    this.restoreHiddenColumns(newHiddenColumns);
    return newHiddenColumns;
  }

  async togglePowerCycle(id: string): Promise<void> {
    await this.fetchCheckAndUpdate(`/_/machine/toggle_powercycle/${id}`, {
      method: 'POST',
    });
  }

  async clearQuarantineAction(id: string): Promise<void> {
    await this.fetchCheckAndUpdate(`/_/machine/clear_quarantined/${id}`, {
      method: 'POST',
    });
  }

  private async clearDevice(e: Event): Promise<void> {
    const id = (e as CustomEvent<string>).detail;
    this.clearDeviceByID(id);
  }

  private async clearDeviceByID(id: string): Promise<void> {
    await this.fetchCheckAndUpdate(`/_/machine/remove_device/${id}`, {
      method: 'POST',
    });
  }

  async deleteDevice(id: string): Promise<void> {
    await this.fetchCheckAndUpdate(`/_/machine/delete_machine/${id}`, {
      method: 'POST',
    });
  }

  private async updateDimensions(e: Event): Promise<void> {
    const info = (e as CustomEvent<UpdateDimensionsDetails>).detail;
    const postBody: SupplyChromeOSRequest = {
      SSHUserIP: info.sshUserIP,
      SuppliedDimensions: info.specifiedDimensions,
    };
    await this.fetchCheckAndUpdate(
      `/_/machine/supply_chromeos/${info.machineID}`,
      {
        method: 'POST',
        body: JSON.stringify(postBody),
      }
    );
  }
}

window.customElements.define('machines-table-sk', MachinesTableSk);
