/**
 * @module infra-sk/modules/task-driver-sk
 * @description <h2><code>task-driver-sk</code></h2>
 *
 * <p>
 * This element displays information about a Task Driver.
 * </p>
 *
 */
import { define } from 'elements-sk/define'
import { escapeAndLinkify } from '../linkify'
import { html, render } from 'lit-html'
import { localeTime, strDuration } from 'common-sk/modules/human'
import { upgradeProperty } from 'elements-sk/upgradeProperty'
import { CollapseSk } from 'elements-sk/collapse-sk/collapse-sk';
import { StepData, StepDisplay, TaskDriverRunDisplay } from '../../../task_driver/modules/json';
import 'elements-sk/collapse-sk'
import 'elements-sk/icon/launch-icon-sk'
import 'elements-sk/styles/buttons'

/**
 * Describes the extra fields that this custom element adds to the JSON-encoded
 * TaskDriverRunDisplay and StepDisplay structs returned by the Go backend.
 */
interface UIInfo {
  expandProps?: boolean;
  expandEnv?: boolean;
  expandChildren?: boolean;
}

/**
 * Convenience type for use in templates that take both a TaskDriverRunDisplay
 * or a StepDisplay struct as their input.
 */
type RunOrStepDisplay = (TaskDriverRunDisplay & UIInfo) | (StepDisplay & UIInfo);

/** Type guard to differentiate between the TaskDriverRunDisplay and StepDisplay types. */
function isTaskDriverRunDisplay(d: RunOrStepDisplay): d is TaskDriverRunDisplay & UIInfo {
  return (d as TaskDriverRunDisplay).properties !== undefined;
}

const tr = (contents: unknown) => html`<tr>${contents}</tr>`;

const td = (contents: unknown) => html`<td>${contents}</td>`;

const propLine = (k: unknown, v: unknown) => html`
  ${tr(html`${td(k)}${td(v)}`)}
`;

const expando = (expanded = false) => html`<span class="expando">[${expanded ? "-" : "+"}]</span>`;

export class TaskDriverSk extends HTMLElement {
  private static stepData = (ele: TaskDriverSk, s: RunOrStepDisplay, d: StepData) => {
    switch(d.type) {
      case "command":
        return propLine("Command", d.data.command.join(" "));
      case "httpRequest":
        return propLine("HTTP Request", d.data.url);
      case "httpResponse":
        return propLine("HTTP Response", d.data.status);
      case "text":
        return propLine(d.data.label, escapeAndLinkify(d.data.value));
      case "log":
        return propLine("Log (" + d.data.name + ")", html`
          <a href="${ele.logLink(s.id!, d.data.id)}" target="_blank">${d.data.name}</a>
      `);
    }
    return "";
  }

  private static stepError = (ele: TaskDriverSk, s: RunOrStepDisplay, e: string, idx: number) => propLine(html`
    <a href="${ele.errLink(s.id!, idx)}" target="_blank">
      Error
    </a>`, html`
    <pre>${e}</pre>
  `);

  private static stepProperties = (ele: TaskDriverSk, s: RunOrStepDisplay) => html`
    <table class="properties">
      ${isTaskDriverRunDisplay(s) && s.properties
        ? html`
          ${s.properties.swarmingServer && s.properties.swarmingTask
            ? propLine("Swarming Task", html`
              <a href="${s.properties.swarmingServer + "/task?id=" + s.properties.swarmingTask + "&show_raw=1"}" target="_blank">${s.properties.swarmingTask}</a>
            `)
            : ""
        }
          ${s.properties.swarmingServer && s.properties.swarmingBot
            ? propLine("Swarming Bot", html`
              <a href="${s.properties.swarmingServer + "/bot?id=" + s.properties.swarmingBot}" target="_blank">${s.properties.swarmingBot}</a>
            `)
            : ""
        }
          ${!s.properties.local
            ? propLine("Task Scheduler", html`
              <a href="https://task-scheduler.skia.org/task/${s.id}" target="_blank">${s.id}</a>
            `)
            : ""
        }
        `
        : ""
      }
      ${s.isInfra ? propLine("Infra", s.isInfra) : ""}
      ${propLine("Started", ele.displayTime(s.started))}
      ${propLine("Finished", ele.displayTime(s.finished))}
      ${s.environment
          ? propLine("Environment", html`
                <a id="button_env_${s.id}" @click=${() => ele.toggleEnv(s)}>
                  ${expando(s.expandEnv)}
                </a>
                <collapse-sk id="env_${s.id}" ?closed="${!s.expandEnv}">
                  ${s.environment.map(env => tr(td(env)))}
                </collapse-sk>
              `)
          : ""
      }
      ${s.data ? s.data.map((d) => TaskDriverSk.stepData(ele, s, d)) : ""}
      ${propLine("Log (combined)", html`
          <a href="${ele.logLink(s.id!)}" target="_blank">all logs</a>
      `)}
      ${s.errors ? s.errors.map((e, idx) => TaskDriverSk.stepError(ele, s, e, idx)) : ""}
    </div>
  `;

  private static stepChildren = (ele: TaskDriverSk, s: RunOrStepDisplay) => html`
    <div class="vert children_link">
      <a id="button_children_${s.id}" @click=${() => ele.toggleChildren(s)}>
        ${expando(s.expandChildren)}
      </a>
      ${s.steps!.length} Children
    </div>
    <collapse-sk id="children_${s.id}" ?closed="${!s.expandChildren}">
      ${s.steps!.map((s) => TaskDriverSk.step(ele, s))}
    </collapse-sk>
  `;

  private static stepInner = (ele: TaskDriverSk, s: RunOrStepDisplay) => html`
    <collapse-sk id="props_${s.id}" ?closed="${!s.expandProps}">
      ${TaskDriverSk.stepProperties(ele, s)}
    </collapse-sk>
    ${s.steps && s.steps.length > 0 ? TaskDriverSk.stepChildren(ele, s) : ""}
  `;

  private static step = (ele: TaskDriverSk, s: RunOrStepDisplay): unknown => html`
    <div class="${ele.stepClass(s)}">
      <div class="vert">
        <a class="horiz" id="button_props_${s.id}" @click=${() => ele.toggleProps(s)}>
          ${expando(s.expandProps)}
        </a>
        <div class="${ele.stepNameClass(s)}">${s.name}</div>
        <div class="horiz duration">${ele.duration(s.started, s.finished)}</div>
        ${!s.parent && ele.hasAttribute('embedded') ? html`
          <div class="horiz">
            <a href="https://task-driver.skia.org/td/${s.id}" target="_blank">
              <launch-icon-sk></launch-icon-sk>
            </a>
          </div>
        ` : ""}
      </div>
      ${TaskDriverSk.stepInner(ele, s)}
    </div>
  `;

  private static template = (ele: TaskDriverSk) => TaskDriverSk.step(ele, ele.data);

  private _data: Partial<TaskDriverRunDisplay> = {};

  connectedCallback() {
    upgradeProperty(this, 'data');
    this.render();
  }

  private parseDate(ts: string): Date | null {
    if (!ts) {
      return null;
    }
    try {
      const d = new Date(ts);
      if (d.getFullYear() < 1970) {
        return null;
      }
      return d;
    } catch(e) {
      return null;
    }
  }

  private displayTime(ts = ''): string {
    let d = this.parseDate(ts);
    if (!d) {
      return "-";
    }
    return localeTime(d);
  }

  private duration(started = '', finished = ''): string {
    let startedDate = this.parseDate(started);
    if (!startedDate) {
      // PubSub messages may arrive out of order, so it's possible that we don't
      // have a start timestemp for a step. Don't try to compute a duration in
      // that case.
      return "(no start time)";
    }
    let finishedDate = this.parseDate(finished);
    if (!finishedDate) {
      // If we don't have a finished timestamp for the step, we can assume that
      // the step simply hasn't finished yet. Compute the duration of the step
      // so far.
      finishedDate = new Date();
    }
    // TODO(borenet): strDuration only gets down to seconds. It'd be nice to
    // give millisecond precision.
    const duration = strDuration((finishedDate.getTime() - startedDate.getTime()) / 1000);
    return duration;
  }

  private toggleChildren(step: RunOrStepDisplay) {
    const collapse = this.querySelector<CollapseSk>(`#children_${step.id}`)!;
    collapse.closed = !collapse.closed;
    step.expandChildren = !collapse.closed;
    this.render();
  }

  private toggleEnv(step: RunOrStepDisplay) {
    const collapse = this.querySelector<CollapseSk>(`#env_${step.id}`)!;
    collapse.closed = !collapse.closed;
    step.expandEnv = !collapse.closed;
    this.render();
  }

  private toggleProps(step: RunOrStepDisplay) {
    let collapse = this.querySelector<CollapseSk>(`#props_${step.id}`)!;
    collapse.closed = !collapse.closed;
    step.expandProps = !collapse.closed;
    this.render();
  }

  private errLink(stepId: string, idx: number): string {
    let link = "/errors/" + this._data.id;
    if (stepId !== this._data.id) {
      link += "/" + stepId;
    }
    return link + "/" + idx;
  }

  private logLink(stepId: string, logId?: string): string {
    let link = "/logs/" + this._data.id;
    if (stepId !== this._data.id) {
      link += "/" + stepId;
    }
    if (logId) {
      link += "/" + logId;
    }
    return link
  }

  // Return true if the step is interesting, ie. it has a result other than
  // SUCCESS (including not yet finished). The root step (which has no parent)
  // is interesting by default.
  private stepIsInteresting(step: StepDisplay): boolean {
    if (!step.parent) {
      return true
    }
    return step.result != "SUCCESS";
  }

  // Process the step data. Return true if the current step is interesting.
  private process(step: RunOrStepDisplay): boolean {
    // Sort the step data, so that the properties end up in a predictable order.
    if (step.data) {
      step.data.sort(function(a, b) {
        if (a.type < b.type) {
          return -1;
        } else if (a.type > b.type) {
          return 1;
        }
        if (a.data.name < b.data.name) {
          return -1;
        }
        return 1;
      });
    }

    // We expand the children of this step if this step is interesting AND if
    // any of the children are interesting. Note that parent steps which do not
    // inherit the failure of one of their children will not be considered
    // interesting unless they fail for another reason.
    let anyChildInteresting = false;
    for (let i = 0; i < (step.steps || []).length; i++) {
      if (this.process(step.steps![i])) {
        anyChildInteresting = true;
      }
    }
    const isInteresting = this.stepIsInteresting(step);
    step.expandChildren = false;
    if (isInteresting && anyChildInteresting) {
      step.expandChildren = true;
    }
    step.expandEnv = false;

    // Step properties take up a lot of space on the screen. Only display them
    // if the step is interesting AND it has no interesting children.
    // Unsuccessful steps which have unsuccessful children are most likely to
    // have inherited the result of their children and so their properties are
    // not as important of those of the failed child step.
    step.expandProps = isInteresting && !anyChildInteresting;

    return isInteresting;
  }

  get data(): TaskDriverRunDisplay { return this._data as TaskDriverRunDisplay; }
  set data(val: TaskDriverRunDisplay) {
    this.process(val);
    this._data = val;
    this.render();
  }

  get embedded(): boolean { return this.hasAttribute('embedded'); }
  set embedded(isEmbedded: boolean) {
    if (isEmbedded) {
      this.setAttribute('embedded', '');
    } else {
      this.removeAttribute('embedded');
    }
    this.render();
  }

  private render() {
    render(TaskDriverSk.template(this), this, {eventContext: this});
  }

  private stepClass(s: StepDisplay): string {
    let res = s.result;
    if (s.isInfra && s.result == "FAILURE") {
      res = "EXCEPTION";
    }
    if (!res) {
      res = "IN_PROGRESS";
    }
    return "step " + res;
  }

  private stepNameClass(s: StepDisplay): string {
    if (s.parent) {
      return "horiz h4";
    }
    return "horiz h2";
  }
}

define('task-driver-sk', TaskDriverSk);
