/**
 * @module module/explore-sk
 * @description <h2><code>explore-sk</code></h2>
 *
 * Main page of Perf, for exploring data.
 */
import { define } from 'elements-sk/define';
import { errorMessage } from 'elements-sk/errorMessage';
import { html } from 'lit-html';
import { jsonOrThrow } from 'common-sk/modules/jsonOrThrow';
import { stateReflector } from 'common-sk/modules/stateReflector';
import { toParamSet } from 'common-sk/modules/query';
import dialogPolyfill from 'dialog-polyfill';
import { TabsSk } from 'elements-sk/tabs-sk/tabs-sk';
import { ParamSet as CommonSkParamSet } from 'common-sk/modules/query';
import { HintableObject } from 'common-sk/modules/hintable';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';

import 'elements-sk/checkbox-sk';
import 'elements-sk/icon/help-icon-sk';
import 'elements-sk/spinner-sk';
import 'elements-sk/styles/buttons';
import 'elements-sk/tabs-panel-sk';
import 'elements-sk/tabs-sk';

import '../../../infra-sk/modules/query-sk';
import '../../../infra-sk/modules/paramset-sk';

import '../commit-detail-panel-sk';
import '../domain-picker-sk';
import '../json-source-sk';
import '../plot-simple-sk';
import '../query-count-sk';
import {
  DataFrame,
  RequestType,
  ParamSet,
  FrameRequest,
  FrameResponse,
  ShiftRequest,
  ShiftResponse,
} from '../json';
import {
  PlotSimpleSk,
  PlotSimpleSkTraceEventDetails,
} from '../plot-simple-sk/plot-simple-sk';
import { CommitDetailPanelSk } from '../commit-detail-panel-sk/commit-detail-panel-sk';
import { JSONSourceSk } from '../json-source-sk/json-source-sk';
import {
  ParamSetSk,
  ParamSetSkClickEventDetail,
} from '../../../infra-sk/modules/paramset-sk/paramset-sk';
import {
  QuerySk,
  QuerySkQueryChangeEventDetail,
} from '../../../infra-sk/modules/query-sk/query-sk';
import { QueryCountSk } from '../query-count-sk/query-count-sk';
import { DomainPickerSk } from '../domain-picker-sk/domain-picker-sk';
import { MISSING_DATA_SENTINEL } from '../plot-simple-sk/plot-simple-sk';

// The trace id of the zero line, a trace of all zeros.
const ZERO_NAME = 'special_zero';

// How often to refresh if the auto-refresh checkmark is checked.
const REFRESH_TIMEOUT = 30 * 1000; // milliseconds

// The default query range in seconds.
const DEFAULT_RANGE_S = 24 * 60 * 60; // 2 days in seconds.

// The index of the params tab.
const PARAMS_TAB_INDEX = 0;

// The index of the commit detail info tab.
const COMMIT_TAB_INDEX = 1;

// The percentage of the current zoom window to pan or zoom on a keypress.
const ZOOM_JUMP_PERCENT = 0.1;

// When we are zooming around and bump into the edges of the graph, how much
// should we widen the range of commits, as a percentage of the currently
// displayed commit.
const RANGE_CHANGE_ON_ZOOM_PERCENT = 0.5;

// The minimum length [right - left] of a zoom range.
const MIN_ZOOM_RANGE = 0.1;

type RequestFrameCallback = (frameResponse: FrameResponse)=> void;

// State is reflected to the URL via stateReflector.
class State {
  begin: number = Math.floor(Date.now() / 1000 - DEFAULT_RANGE_S);

  end: number = Math.floor(Date.now() / 1000);

  formulas: string[] = [];

  queries: string[] = [];

  keys: string = ''; // The id of the shortcut to a list of trace keys.

  xbaroffset: number = -1; // The offset of the commit in the repo.

  showZero: boolean = true;

  autoRefresh: boolean = false;

  numCommits: number = 50;

  requestType: RequestType = 1; // TODO(jcgregorio) Use constants in domain-picker-sk.
}

// TODO(jcgregorio) Move to a 'key' module.
// Returns true if paramName=paramValue appears in the given structured key.
function _matches(key: string, paramName: string, paramValue: string): boolean {
  return key.indexOf(`,${paramName}=${paramValue},`) >= 0;
}

// TODO(jcgregorio) Move to a 'key' module.
// Parses the structured key and returns a populated object with all
// the param names and values.
function toObject(key: string): { [key: string]: string } {
  const ret: { [key: string]: string } = {};
  key.split(',').forEach((s, i) => {
    if (i === 0) {
      return;
    }
    if (s === '') {
      return;
    }
    const parts = s.split('=');
    if (parts.length !== 2) {
      return;
    }
    ret[parts[0]] = parts[1];
  });
  return ret;
}

interface RangeChange {
  /**
   * If true then do a range change with the provided offsets, otherwise just
   * do a zoom.
   */
  rangeChange: boolean;

  newOffsets?: [number, number];
}

// clamp ensures a number is not negative.
function clampToNonNegative(x: number): number {
  if (x < 0) {
    return 0;
  }
  return x;
}

/**
 * Determines if a range change is needed based on a zoom request, and if so
 * calculates what the new range change should be.
 *
 * @param zoom is the requested zoom.
 * @param clampedZoom is the requested zoom clamped to the current dataframe.
 * @param offsets are the commit offset of the first and last value in the
 * dataframe.
 */
export function calculateRangeChange(
  zoom: [number, number],
  clampedZoom: [number, number],
  offsets: [number, number],
): RangeChange {
  // How much we will change the offset if we zoom beyond an edge.
  const offsetDelta = Math.floor(
    (offsets[1] - offsets[0]) * RANGE_CHANGE_ON_ZOOM_PERCENT,
  );
  const exceedsLeftEdge = zoom[0] !== clampedZoom[0];
  const exceedsRightEdge = zoom[1] !== clampedZoom[1];
  if (exceedsLeftEdge && exceedsRightEdge) {
    // shift both
    return {
      rangeChange: true,
      newOffsets: [
        clampToNonNegative(offsets[0] - offsetDelta),
        offsets[1] + offsetDelta,
      ],
    };
  } if (exceedsLeftEdge) {
    // shift left
    return {
      rangeChange: true,
      newOffsets: [clampToNonNegative(offsets[0] - offsetDelta), offsets[1]],
    };
  } if (exceedsRightEdge) {
    // shift right
    return {
      rangeChange: true,
      newOffsets: [offsets[0], offsets[1] + offsetDelta],
    };
  }
  return {
    rangeChange: false,
  };
}

export class ExploreSk extends ElementSk {
  private _dataframe: DataFrame = {
    traceset: {},
    header: [],
    paramset: {},
    skip: 0,
  };

  // The state that does into the URL.
  private state = new State();

  // Are we waiting on data from the server.
  private _spinning: boolean = false;

  // The id of the current frame request. Will be the empty string if there
  // is no pending request.
  private _requestId = '';

  private _numShift = window.sk.perf.num_shift;

  // The id of the interval timer if we are refreshing.
  private _refreshId = -1;

  // All the data converted into a CVS blob to download.
  private _csvBlobURL: string = '';


  private _initialized: boolean = false;

  private commits: CommitDetailPanelSk | null = null;

  private commitsTab: HTMLButtonElement | null = null;

  private detailTab: TabsSk | null = null;

  private formula: HTMLTextAreaElement | null = null;

  private jsonsource: JSONSourceSk | null = null;

  private paramset: ParamSetSk | null = null;

  private percent: HTMLSpanElement | null = null;

  private plot: PlotSimpleSk | null = null;

  private query: QuerySk | null = null;

  private queryCount: QueryCountSk | null = null;

  private range: DomainPickerSk | null = null;

  private simpleParamset: ParamSetSk | null = null;

  private summary: ParamSetSk | null = null;

  private traceID: HTMLSpanElement | null = null;

  private csvDownload: HTMLAnchorElement | null = null;

  private queryDialog: HTMLDialogElement | null = null;

  private helpDialog: HTMLDialogElement | null = null;

  constructor() {
    super(ExploreSk.template);
  }

  private static template = (ele: ExploreSk) => html`
  <div id=buttons>
    <button @click=${ele.openQuery}>Query</button>
    <div id=traceButtons ?hide_if_no_data=${!ele.hasData()}>
      <button
        @click=${() => ele.removeAll(false)}
        title='Remove all the traces.'>
        Remove All
      </button>

      <button
        @click=${ele.removeHighlighted}
        ?hidden=${!(ele.plot && ele.plot!.highlight.length)}
        title='Remove all the highlighted traces.'>
        Remove Highlighted
      </button>

      <button
        @click=${ele.highlightedOnly}
        ?hidden=${!(ele.plot && ele.plot!.highlight.length)}
        title='Remove all but the highlighted traces.'>
        Highlighted Only
      </button>

      <span title='Number of commits skipped between each point displayed.' ?hidden=${ele.isZero(
    ele._dataframe.skip,
  )} id=skip>${ele._dataframe.skip}</span>
      <checkbox-sk name=zero @change=${ele.zeroChangeHandler} ?checked=${
    ele.state.showZero
  } label='Zero' title='Toggle the presence of the zero line.'>Zero</checkbox-sk>
      <checkbox-sk name=auto @change=${ele.autoRefreshHandler} ?checked=${
    ele.state.autoRefresh
  } label='Auto-refresh'   title='Auto-refresh the data displayed in the graph.'>Auto-Refresh</checkbox-sk>
      <div
        id=calcButtons
        ?hide_if_no_data=${!ele.hasData()}>
        <button
          @click=${ele.norm}
          title='Apply norm() to all the traces.'>
          Normalize
        </button>
        <button
          @click=${ele.scaleByAvg}
          title='Apply scale_by_avg() to all the traces.'>
          Scale By Avg
        </button>
        <button
          @click=${ele.csv}
          title='Download all displayed data as a CSV file.'>
          CSV
        </button>
        <a href='' target=_blank download='traces.csv' id=csv_download></a>
      </div>
    </div>
  </div>

  <div id=spin-overlay>
    <plot-simple-sk
      summary
      width=1200
      height=400
      id=plot
      ?spinning=${ele.spinning}
      @trace_selected=${ele.traceSelected}
      @zoom=${ele.plotZoom}
      @trace_focused=${ele.plotTraceFocused}
      ?hide_if_no_data=${!ele.hasData()}
      >
    </plot-simple-sk>
    <div id=spin-container ?spinning=${ele.spinning}>
      <spinner-sk id=spinner ?active=${ele.spinning}></spinner-sk>
      <span id=percent></span>
    </div>
  </div>

  <dialog id='query-dialog'>
    <h2>Query</h2>
    <div class=query-parts>
      <query-sk
        id=query
        @query-change=${ele.queryChangeHandler}
        @query-change-delayed=${ele.queryChangeDelayedHandler}
        > </query-sk>
        <div id=selections>
          <h3>Selections</h3>
          <paramset-sk id=summary></paramset-sk>
          <div class=query-counts>
            Matches: <query-count-sk url='/_/count/' @paramset-changed=${
              ele.paramsetChanged
            }>
            </query-count-sk>
          </div>
          <button @click=${() => ele.add(true)} class=action>Plot</button>
          <button @click=${() => ele.add(false)}>Add to Plot</button>
        </div>
    </div>
    <details>
      <summary>Time Range</summary>
      <domain-picker-sk id=range>
      </domain-picker-sk>
    </details>

    <details>
      <summary>Calculated Traces</summary>
      <div class=formulas>
        <textarea id=formula rows=3 cols=80></textarea>
        <button @click=${() => ele.addCalculated(true)}>Plot</button>
        <button @click=${() => ele.addCalculated(false)}>Add to Plot</button>
        <a href=/help/ target=_blank>
          <help-icon-sk></help-icon-sk>
        </a>
      </div>
    </details>
  </dialog>

  <dialog id=help>
    <h2>Perf Help</h2>
    <table>
      <tr><td colspan=2><h3>Mouse Controls</h3></td></tr>
      <tr><td class=mono>Hover</td><td>Snap crosshair to closest point.</td></tr>
      <tr><td class=mono>Shift + Hover</td><td>Highlight closest trace.</td></tr>
      <tr><td class=mono>Click</td><td>Select closest point.</td></tr>
      <tr><td colspan=2><h3>Keyboard Controls</h3></td></tr>
      <tr><td class=mono>'w'/'s'</td><td>Zoom in/out.<sup>1</sup></td></tr>
      <tr><td class=mono>'a'/'d'</td><td>Pan left/right.<sup>1</sup></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>
      <sup>1</sup> And Dvorak equivalents.
    </div>
  </dialog>

    <div id=tabs ?hide_if_no_data=${!ele.hasData()}>
      <tabs-sk id=detailTab>
        <button>Params</button>
        <button id=commitsTab disabled>Details</button>
      </tabs-sk>
      <tabs-panel-sk>
        <div>
          <p>
            <b>Trace ID</b>: <span title='Trace ID' id=trace_id></span>
          </p>
          <paramset-sk
            id=paramset
            clickable_values
            @paramset-key-value-click=${ele.paramsetKeyValueClick}>
            </paramset-sk>
        </div>
        <div id=details>
          <paramset-sk
            id=simple_paramset
            clickable_values
            @paramset-key-value-click=${ele.paramsetKeyValueClick}
            >
          </paramset-sk>
          <div>
            <commit-detail-panel-sk id=commits selectable></commit-detail-panel-sk>
            <json-source-sk id=jsonsource></json-source-sk>
          </div>
        </div>
      </tabs-panel-sk>
    </div>
  `;

  connectedCallback(): void {
    super.connectedCallback();
    if (this._initialized) {
      return;
    }
    this._initialized = true;
    this._render();

    this.commits = this.querySelector('#commits');
    this.commitsTab = this.querySelector('#commitsTab');
    this.detailTab = this.querySelector('#detailTab');
    this.formula = this.querySelector('#formula');
    this.jsonsource = this.querySelector('#jsonsource');
    this.paramset = this.querySelector('#paramset');
    this.percent = this.querySelector('#percent');
    this.plot = this.querySelector('#plot');
    this.query = this.querySelector('#query');
    this.queryCount = this.querySelector('query-count-sk');
    this.range = this.querySelector('#range');
    this.simpleParamset = this.querySelector('#simple_paramset');
    this.summary = this.querySelector('#summary');
    this.traceID = this.querySelector('#trace_id');
    this.csvDownload = this.querySelector('#csv_download');
    this.queryDialog = this.querySelector('#query-dialog');
    dialogPolyfill.registerDialog(this.queryDialog!);
    this.helpDialog = this.querySelector('#help');
    dialogPolyfill.registerDialog(this.helpDialog!);

    // Populate the query element.
    const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;

    fetch(`/_/initpage/?tz=${tz}`, {
      method: 'GET',
    })
      .then(jsonOrThrow)
      .then((json) => {
        const now = Math.floor(Date.now() / 1000);
        this.state.begin = now - 60 * 60 * 24;
        this.state.end = now;
        this.range!.state = {
          begin: this.state.begin,
          end: this.state.end,
          num_commits: this.state.numCommits,
          request_type: this.state.requestType,
        };

        this.query!.key_order = window.sk.perf.key_order || [];
        this.query!.paramset = json.dataframe.paramset;

        // Remove the paramset so it doesn't get displayed in the Params tab.
        json.dataframe.paramset = {};

        // From this point on reflect the state to the URL.
        this.startStateReflector();
      })
      .catch(errorMessage);

    document.addEventListener('keydown', (e) => this.keyDown(e));
  }

  // 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 keyDown(e: KeyboardEvent) {
    // Ignore IME composition events.
    if (e.isComposing || e.keyCode === 229) {
      return;
    }
    switch (e.key) {
      case '?':
        this.helpDialog!.showModal();
        break;
      case ',': // dvorak
      case 'w':
        this.zoomInKey();
        break;
      case 'o': // dvorak
      case 's':
        this.zoomOutKey();
        break;
      case 'a':
        this.zoomLeftKey();
        break;
      case 'e': // dvorak
      case 'd':
        this.zoomRightKey();
        break;
      default:
        break;
    }
  }

  /**
   * The current zoom and the length between the left and right edges of
   * the zoom as an object of the form:
   *
   *   {
   *     zoom: [2.0, 12.0],
   *     delta: 10.0,
   *   }
   */
  private getCurrentZoom() {
    let zoom = this.plot!.zoom;
    if (zoom === null) {
      zoom = [0, this._dataframe.header!.length - 1];
    }
    let delta = zoom[1] - zoom[0];
    if (delta < MIN_ZOOM_RANGE) {
      const mid = (zoom[0] + zoom[1]) / 2;
      zoom[0] = mid - MIN_ZOOM_RANGE / 2;
      zoom[1] = mid + MIN_ZOOM_RANGE / 2;
      delta = MIN_ZOOM_RANGE;
    }
    return {
      zoom,
      delta,
    };
  }

  /**
   * Clamp a single zoom endpoint.
   */
  private clampZoomIndexToDataFrame(z: number): number {
    if (z < 0) {
      z = 0;
    }
    if (z > this._dataframe.header!.length - 1) {
      z = this._dataframe.header!.length - 1;
    }
    return z;
  }

  /**
   * Fixes up the zoom range so it always make sense.
   *
   * @param {Array<Number>} zoom - The zoom range.
   * @returns {Array<Number>} The zoom range.
   */
  private rationalizeZoom(zoom: [number, number]) {
    if (zoom[0] > zoom[1]) {
      const left = zoom[0];
      zoom[0] = zoom[1];
      zoom[1] = left;
    }
    return zoom;
  }

  /**
   * Zooms to the desired range, or changes the range of commits being displayed
   * if the zoom range extends past either end of the current commits.
   *
   * @param zoom is the desired zoom range. Each number is an index into the
   * dataframe.
   */
  private zoomOrRangeChange(zoom: [number, number]) {
    zoom = this.rationalizeZoom(zoom);
    const clampedZoom: [number, number] = [
      this.clampZoomIndexToDataFrame(zoom[0]),
      this.clampZoomIndexToDataFrame(zoom[1]),
    ];
    const offsets: [number, number] = [
      this._dataframe.header![0]!.offset,
      this._dataframe.header![this._dataframe.header!.length - 1]!.offset,
    ];

    const result = calculateRangeChange(zoom, clampedZoom, offsets);
    if (result.rangeChange) {
      // Convert the offsets into timestamps, which are needed when building
      // dataframes.
      const req: ShiftRequest = {
        begin: result.newOffsets![0],
        end: result.newOffsets![1],
      };
      fetch('/_/shift/', {
        method: 'POST',
        body: JSON.stringify(req),
        headers: {
          'Content-Type': 'application/json',
        },
      })
        .then(jsonOrThrow)
        .then((json: ShiftResponse) => {
          this.state.begin = json.begin;
          this.state.end = json.end;
          this.state.requestType = 0;
          this._stateHasChanged();
          this.rangeChangeImpl();
        })
        .catch(errorMessage);
    } else {
      this.plot!.zoom = zoom;
    }
  }

  private zoomInKey() {
    const cz = this.getCurrentZoom();
    const zoom: [number, number] = [
      cz.zoom[0] + ZOOM_JUMP_PERCENT * cz.delta,
      cz.zoom[1] - ZOOM_JUMP_PERCENT * cz.delta,
    ];
    this.zoomOrRangeChange(zoom);
  }

  private zoomOutKey() {
    const cz = this.getCurrentZoom();
    const zoom: [number, number] = [
      cz.zoom[0] - ZOOM_JUMP_PERCENT * cz.delta,
      cz.zoom[1] + ZOOM_JUMP_PERCENT * cz.delta,
    ];
    this.zoomOrRangeChange(zoom);
  }

  private zoomLeftKey() {
    const cz = this.getCurrentZoom();
    const zoom: [number, number] = [
      cz.zoom[0] - ZOOM_JUMP_PERCENT * cz.delta,
      cz.zoom[1] - ZOOM_JUMP_PERCENT * cz.delta,
    ];
    this.zoomOrRangeChange(zoom);
  }

  private zoomRightKey() {
    const cz = this.getCurrentZoom();
    const zoom: [number, number] = [
      cz.zoom[0] + ZOOM_JUMP_PERCENT * cz.delta,
      cz.zoom[1] + ZOOM_JUMP_PERCENT * cz.delta,
    ];
    this.zoomOrRangeChange(zoom);
  }

  /**  Returns true if we have any traces to be displayed. */
  private hasData() {
    return Object.keys(this._dataframe.traceset).length > 0 || this._spinning;
  }

  /** Open the query dialog box. */
  private openQuery() {
    this.queryDialog!.showModal();
  }

  private paramsetChanged(e: CustomEvent<ParamSet>) {
    this.query!.paramset = e.detail as CommonSkParamSet;
  }

  private queryChangeDelayedHandler(
    e: CustomEvent<QuerySkQueryChangeEventDetail>,
  ) {
    this.queryCount!.current_query = e.detail.q;
  }

  /** Reflect the current query to the query summary. */
  private queryChangeHandler(e: CustomEvent<QuerySkQueryChangeEventDetail>) {
    const query = e.detail.q;
    this.summary!.paramsets = [toParamSet(query)];
    const formula = this.formula!.value;
    if (formula === '') {
      this.formula!.value = `filter("${query}")`;
    } else if ((formula.match(/"/g) || []).length === 2) {
      // Only update the filter query if there's one string in the formula.
      this.formula!.value = formula.replace(/".*"/, `"${query}"`);
    }
  }

  /** Reflect the focused trace in the paramset. */
  private plotTraceFocused(e: CustomEvent<PlotSimpleSkTraceEventDetails>) {
    this.paramset!.highlight = toObject(e.detail.name);
    this.traceID!.textContent = e.detail.name;
  }

  /** User has zoomed in on the graph. */
  private plotZoom() {
    this._render();
  }

  /** Highlight a trace when it is clicked on. */
  private traceSelected(e: CustomEvent<PlotSimpleSkTraceEventDetails>) {
    this.plot!.highlight = [e.detail.name];
    this.commits!.details = [];

    const x = e.detail.x;
    // loop backwards from x until you get the next
    // non MISSING_DATA_SENTINEL point.
    const commits = [this._dataframe.header![x]?.offset];
    const trace = this._dataframe.traceset[e.detail.name];
    for (let i = x - 1; i >= 0; i--) {
      if (trace![i] !== MISSING_DATA_SENTINEL) {
        break;
      }
      commits.push(this._dataframe.header![i]?.offset);
    }
    // Convert the trace id into a paramset to display.
    const params: { [key: string]: string } = toObject(e.detail.name);
    const paramset: ParamSet = {};
    Object.keys(params).forEach((key) => {
      paramset[key] = [params[key]];
    });

    this._render();

    // Request populated commits from the server.
    fetch('/_/cid/', {
      method: 'POST',
      body: JSON.stringify(commits),
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then(jsonOrThrow)
      .then((json) => {
        this.commits!.details = json;
        this.commitsTab!.disabled = false;
        this.simpleParamset!.paramsets = [paramset as CommonSkParamSet];
        this.detailTab!.selected = COMMIT_TAB_INDEX;
        this.jsonsource!.cid = commits[0]!;
        this.jsonsource!.traceid = e.detail.name;
      })
      .catch(errorMessage);
  }

  private startStateReflector() {
    this._stateHasChanged = stateReflector(
      () => (this.state as unknown) as HintableObject,
      (hintableState) => {
        let state = (hintableState as unknown) as State;
        state = this.rationalizeTimeRange(state);
        this.state = state;
        this.range!.state = {
          begin: this.state.begin,
          end: this.state.end,
          num_commits: this.state.numCommits,
          request_type: this.state.requestType,
        };

        this._render();
        // If there is at least one query, the use the last one to repopulate the
        // query-sk dialog.
        const numQueries = this.state.queries.length;
        if (numQueries >= 1) {
          this.query!.current_query = this.state.queries[numQueries - 1];
          this.summary!.paramsets = [
            toParamSet(this.state.queries[numQueries - 1]),
          ];
        }
        this.zeroChanged();
        this.autoRefreshChanged();
        this.rangeChangeImpl();
      },
    );
  }

  /**
   * Fixes up the time ranges in the state that came from query values.
   *
   * It is possible for the query URL to specify just the begin or end time,
   * which may end up giving us an inverted time range, i.e. end < begin.
   */
  private rationalizeTimeRange(state: State): State {
    if (state.end <= state.begin) {
      // If dense then just make sure begin is before end.
      if (state.requestType === 1) {
        state.begin = state.end - DEFAULT_RANGE_S;
      } else if (this.state.begin !== state.begin) {
        state.end = state.begin + DEFAULT_RANGE_S;
      } else {
        // They set 'end' in the URL.
        state.begin = state.end - DEFAULT_RANGE_S;
      }
    }
    return state;
  }

  private paramsetKeyValueClick(e: CustomEvent<ParamSetSkClickEventDetail>) {
    const keys: string[] = [];
    Object.keys(this._dataframe.traceset).forEach((key) => {
      if (_matches(key, e.detail.key, e.detail.value!)) {
        keys.push(key);
      }
    });
    // Additively highlight if the ctrl key is pressed.
    if (e.detail.ctrl) {
      this.plot!.highlight = this.plot!.highlight.concat(keys);
    } else {
      this.plot!.highlight = keys;
    }
    this._render();
  }

  /** Create a FrameRequest that will re-create the current state of the page. */
  private requestFrameBodyFullFromState(): FrameRequest {
    return {
      begin: this.state.begin,
      end: this.state.end,
      num_commits: this.state.numCommits,
      request_type: this.state.requestType,
      formulas: this.state.formulas,
      queries: this.state.queries,
      keys: this.state.keys,
      hidden: [],
      tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
    };
  }

  /** Reload all the queries/formulas on the given time range. */
  private rangeChangeImpl() {
    if (!this.state) {
      return;
    }
    if (
      this.state.formulas.length === 0
      && this.state.queries.length === 0
      && this.state.keys === ''
    ) {
      return;
    }

    if (this.traceID) {
      this.traceID.textContent = '';
    }
    const body = this.requestFrameBodyFullFromState();
    const switchToTab = body.formulas!.length > 0 || body.queries!.length > 0 || body.keys !== '';
    this.requestFrame(body, (json) => {
      if (json == null) {
        errorMessage('Failed to find any matching traces.');
        return;
      }
      this.plot!.removeAll();
      this.addTraces(json, switchToTab);
      this._render();
    });
  }

  private zeroChangeHandler(e: MouseEvent) {
    this.state.showZero = (e.target! as HTMLInputElement).checked;
    this._stateHasChanged();
    this.zeroChanged();
  }

  private zeroChanged() {
    if (!this._dataframe.header) {
      return;
    }
    if (this.state.showZero) {
      const lines: { [key: string]: number[] } = {};
      lines[ZERO_NAME] = Array(this._dataframe.header.length).fill(0);
      this.plot!.addLines(lines, []);
    } else {
      this.plot!.deleteLines([ZERO_NAME]);
    }
  }

  private autoRefreshHandler(e: MouseEvent) {
    this.state.autoRefresh = (e.target! as HTMLInputElement).checked;
    this._stateHasChanged();
    this.autoRefreshChanged();
  }

  private autoRefreshChanged() {
    if (!this.state.autoRefresh) {
      if (this._refreshId !== -1) {
        clearInterval(this._refreshId);
      }
    } else {
      this._refreshId = window.setInterval(
        () => this.autoRefresh(),
        REFRESH_TIMEOUT,
      );
    }
  }

  private autoRefresh() {
    // Update end to be now.
    this.state.end = Math.floor(Date.now() / 1000);
    const body = this.requestFrameBodyFullFromState();
    const switchToTab = body.formulas!.length > 0 || body.queries!.length > 0 || body.keys !== '';
    this.requestFrame(body, (json) => {
      this.plot!.removeAll();
      this.addTraces(json, switchToTab);
    });
  }

  /**
   * Add traces to the display. Always called from within the
   * this._requestFrame() callback.
   *
   * @param {Object} json - The parsed JSON returned from the server.
   * otherwise replace them all with the new ones.
   * @param {Boolean} tab - If true then switch to the Params tab.
   */
  private addTraces(json: FrameResponse, tab: boolean) {
    const dataframe = json.dataframe!;
    if (dataframe.traceset === null) {
      return;
    }

    // Add in the 0-trace.
    if (this.state.showZero) {
      dataframe.traceset[ZERO_NAME] = Array(dataframe.header!.length).fill(0);
    }

    this._dataframe = dataframe;
    this.plot!.removeAll();
    const labels: Date[] = [];
    dataframe.header!.forEach((header) => {
      labels.push(new Date(header!.timestamp * 1000));
    });

    this.plot!.addLines(dataframe.traceset, labels);

    // Normalize bands to be just offsets.
    const bands: number[] = [];
    dataframe.header!.forEach((h, i) => {
      if (json.skps!.indexOf(h!.offset) !== -1) {
        bands.push(i);
      }
    });
    this.plot!.bands = bands;

    // Populate the xbar if present.
    if (this.state.xbaroffset !== -1) {
      const xbaroffset = this.state.xbaroffset;
      let xbar = -1;
      this._dataframe.header!.forEach((h, i) => {
        if (h!.offset === xbaroffset) {
          xbar = i;
        }
      });
      if (xbar !== -1) {
        this.plot!.xbar = xbar;
      } else {
        this.plot!.xbar = -1;
      }
    } else {
      this.plot!.xbar = -1;
    }

    // Populate the paramset element.
    this.paramset!.paramsets = [dataframe.paramset as CommonSkParamSet];
    if (tab) {
      this.detailTab!.selected = PARAMS_TAB_INDEX;
    }
  }

  /**
   * Plot the traces that match this._query.current_query.
   *
   * @param replace - If true then replace all the traces with ones
   * that match this query, otherwise add them to the current traces being
   * displayed.
   */
  private add(replace: boolean) {
    this.queryDialog!.close();
    const q = this.query!.current_query;
    if (!q || q.trim() === '') {
      errorMessage('The query must not be empty.');
      return;
    }
    this.state.begin = this.range!.state.begin;
    this.state.end = this.range!.state.end;
    this.state.numCommits = this.range!.state.num_commits;
    this.state.requestType = this.range!.state.request_type;
    if (replace) {
      this.removeAll(true);
    }
    if (this.state.queries.indexOf(q) === -1) {
      this.state.queries.push(q);
    }
    this._stateHasChanged();
    const body = this.requestFrameBodyFullFromState();
    this.requestFrame(body, (json) => {
      this.addTraces(json, true);
    });
  }

  /**
   * Removes all traces.
   *
   * @param skipHistory  If true then don't update the URL. Used
   * in calls like _normalize() where this is just an intermediate state we
   * don't want in history.
   */
  private removeAll(skipHistory: boolean) {
    this.state.formulas = [];
    this.state.queries = [];
    this.state.keys = '';
    this.plot!.removeAll();
    this._dataframe.traceset = {};
    this.paramset!.paramsets = [];
    this.traceID!.textContent = '';
    this.detailTab!.selected = PARAMS_TAB_INDEX;
    this._render();
    if (!skipHistory) {
      this._stateHasChanged();
    }
  }

  /**
   * When Remove Highlighted or Highlighted Only are pressed then create a
   * shortcut for just the traces that are displayed.
   *
   * Note that removing a trace doesn't work if the trace came from a
   * formula that returns multiple traces. This is a known issue that
   * isn't currently worth solving.
   *
   * Returns the Promise that's creating the shortcut, or undefined if
   * there isn't a shortcut to create.
   */
  private reShortCut(keys: string[]) {
    if (keys.length === 0) {
      this.state.keys = '';
      this.state.queries = [];
      return undefined;
    }
    const state = {
      keys,
    };
    return fetch('/_/keys/', {
      method: 'POST',
      body: JSON.stringify(state),
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then(jsonOrThrow)
      .then((json) => {
        this.state.keys = json.id;
        this.state.queries = [];
        this._stateHasChanged();
        this._render();
      })
      .catch(errorMessage);
  }

  /**
   * Create a shortcut for all of the traces currently being displayed.
   *
   * Returns the Promise that's creating the shortcut, or undefined if
   * there isn't a shortcut to create.
   */
  private shortcutAll() {
    const toShortcut: string[] = [];

    Object.keys(this._dataframe.traceset).forEach((key) => {
      if (key[0] === ',') {
        toShortcut.push(key);
      }
    });

    return this.reShortCut(toShortcut);
  }

  // Apply norm() to all the traces currently being displayed.
  private norm() {
    const promise = this.shortcutAll();
    if (!promise) {
      errorMessage('No traces to normalize.');
      return;
    }
    promise.then(() => {
      const f = `norm(shortcut("${this.state.keys}"))`;
      this.removeAll(true);
      const body = this.requestFrameBodyFullFromState();
      Object.assign(body, {
        formulas: [f],
      });
      this.state.formulas.push(f);
      this._stateHasChanged();
      this.requestFrame(body, (json) => {
        this.addTraces(json, false);
      });
    });
  }

  /** Apply scale_by_avg() to all the traces currently being displayed. */
  private scaleByAvg() {
    const promise = this.shortcutAll();
    if (!promise) {
      errorMessage('No traces to scale.');
      return;
    }
    promise.then(() => {
      const f = `scale_by_avg(shortcut("${this.state.keys}"))`;
      this.removeAll(true);
      const body = this.requestFrameBodyFullFromState();
      Object.assign(body, {
        formulas: [f],
      });
      this.state.formulas.push(f);
      this._stateHasChanged();
      this.requestFrame(body, (json) => {
        this.addTraces(json, false);
      });
    });
  }

  private removeHighlighted() {
    const ids = this.plot!.highlight;
    const toShortcut: string[] = [];

    Object.keys(this._dataframe.traceset).forEach((key) => {
      if (ids.indexOf(key) !== -1) {
        // Detect if it is a formula being removed.
        if (this.state.formulas.indexOf(key) !== -1) {
          this.state.formulas.splice(this.state.formulas.indexOf(key), 1);
        }
        return;
      }
      if (key[0] === ',') {
        toShortcut.push(key);
      }
    });

    // Remove the traces from the traceset so they don't reappear.
    ids.forEach((key) => {
      if (this._dataframe.traceset[key] !== undefined) {
        delete this._dataframe.traceset[key];
      }
    });
    this.plot!.deleteLines(ids);
    this.plot!.highlight = [];
    this.reShortCut(toShortcut);
  }

  private highlightedOnly() {
    const ids = this.plot!.highlight;
    const toremove: string[] = [];
    const toShortcut: string[] = [];

    Object.keys(this._dataframe.traceset).forEach((key) => {
      if (ids.indexOf(key) === -1 && !key.startsWith('special')) {
        // Detect if it is a formula being removed.
        if (this.state.formulas.indexOf(key) !== -1) {
          this.state.formulas.splice(this.state.formulas.indexOf(key), 1);
        } else {
          toremove.push(key);
        }
        return;
      }
      if (key[0] === ',') {
        toShortcut.push(key);
      }
    });

    // Remove the traces from the traceset so they don't reappear.
    toremove.forEach((key) => {
      delete this._dataframe.traceset[key];
    });

    this.plot!.deleteLines(toremove);
    this.plot!.highlight = [];
    this.reShortCut(toShortcut);
  }

  /**
   * Plot the traces from the formula in this._formula.value;
   *
   * @param replace - If true then replace all the traces with the
   * calculated traces from this formula, otherwise add the calculated traces to
   * the current traces being displayed.
   */
  private addCalculated(replace: boolean) {
    this.queryDialog!.close();
    const f = this.formula!.value;
    if (f.trim() === '') {
      errorMessage('The formula must not be empty.');
      return;
    }

    this.state.begin = this.range!.state.begin;
    this.state.end = this.range!.state.end;
    this.state.numCommits = this.range!.state.num_commits;
    this.state.requestType = this.range!.state.request_type;

    if (replace) {
      this.removeAll(true);
    }
    if (this.state.formulas.indexOf(f) === -1) {
      this.state.formulas.push(f);
    }
    const body = this.requestFrameBodyFullFromState();
    this._stateHasChanged();
    this.requestFrame(body, (json) => {
      this.addTraces(json, false);
    });
  }

  /** Common catch function for _requestFrame and _checkFrameRequestStatus. */
  private catch(msg: string) {
    this._requestId = '';
    if (msg) {
      errorMessage(msg, 10000);
    }
    this.percent!.textContent = '';
    this.spinning = false;
  }

  /** @prop spinning - True if we are waiting to retrieve data from
   * the server.
   */
  set spinning(b: boolean) {
    this._spinning = b;
    this._render();
  }

  get spinning(): boolean {
    return this._spinning;
  }

  /**
   * Requests a new dataframe, where body is a serialized FrameRequest:
   *
   * {
   *    begin:    1448325780,
   *    end:      1476706336,
   *    formulas: ["ave(filter("name=desk_nytimes.skp&sub_result=min_ms"))"],
   *    hidden:   [],
   *    queries:  [
   *        "name=AndroidCodec_01_original.jpg_SampleSize8",
   *        "name=AndroidCodec_1.bmp_SampleSize8"],
   *    tz:       "America/New_York"
   * };
   *
   * The 'cb' callback function will be called with the decoded JSON body
   * of the response once it's available.
   */
  private requestFrame(body: FrameRequest, cb: RequestFrameCallback) {
    body.tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
    if (this._requestId !== '') {
      errorMessage('There is a pending query already running.');
      return;
    }
    this._requestId = 'About to make request';

    this.spinning = true;

    fetch('/_/frame/start', {
      method: 'POST',
      body: JSON.stringify(body),
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then(jsonOrThrow)
      .then((json) => {
        this._requestId = json.id;
        this.checkFrameRequestStatus(cb);
      })
      .catch((msg) => this.catch(msg));
  }

  /**
   * Periodically check the status of a pending FrameRequest, calling the 'cb'
   * callback with the decoded JSON upon success.
   */
  private checkFrameRequestStatus(cb: RequestFrameCallback) {
    fetch(`/_/frame/status/${this._requestId}`, {
      method: 'GET',
    })
      .then(jsonOrThrow)
      .then((json) => {
        if (json.state === 'Running') {
          this.percent!.textContent = `${Math.floor(json.percent * 100)}%`;
          window.setTimeout(() => this.checkFrameRequestStatus(cb), 300);
        } else {
          fetch(`/_/frame/results/${this._requestId}`, {
            method: 'GET',
          })
            .then(jsonOrThrow)
            .then((frameResponse: FrameResponse) => {
              cb(frameResponse);
              this.catch(frameResponse.msg);
            })
            .catch((msg) => this.catch(msg));
        }
      })
      .catch((msg) => this.catch(msg));
  }

  // Download all the displayed data as a CSV file.
  private csv() {
    if (this._csvBlobURL) {
      URL.revokeObjectURL(this._csvBlobURL);
      this._csvBlobURL = '';
    }
    const csv = [];
    let line: (string | number)[] = ['id'];
    this._dataframe.header!.forEach((_, i) => {
      // TODO(jcgregorio) Look up the git hash and use that as the header.
      line.push(i.toString());
    });
    csv.push(line.join(','));
    Object.keys(this._dataframe.traceset).forEach((traceId) => {
      if (traceId === ZERO_NAME) {
        return;
      }
      line = [`"${traceId}"`];
      this._dataframe.traceset[traceId]!.forEach((f) => {
        if (f !== MISSING_DATA_SENTINEL) {
          line.push(f);
        } else {
          line.push('');
        }
      });
      csv.push(line.join(','));
    });
    const blob = new Blob([csv.join('\n')], { type: 'text/csv' });
    const url = URL.createObjectURL(blob);
    this.csvDownload!.href = url;
    this._csvBlobURL = url;
    this.csvDownload!.click();
  }

  private isZero(n: number) {
    return n === 0;
  }
}

define('explore-sk', ExploreSk);
