// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {LitElement, html, css} from 'lit-element';
import qs from 'qs';
import page from 'page';

import {prpcClient} from 'prpc-client-instance.js';
import {linearRegression} from 'shared/math.js';
import './chops-chart.js';
import {urlWithNewParams, createObjectComparisonFunc} from 'shared/helpers.js';

const DEFAULT_NUM_DAYS = 90;
const SECONDS_IN_DAY = 24 * 60 * 60;
const MAX_QUERY_SIZE = 90;
const MAX_DISPLAY_LINES = 10;
const predRangeType = Object.freeze({
  NEXT_MONTH: 0,
  NEXT_QUARTER: 1,
  NEXT_50: 2,
  HIDE: 3,
});
const CHART_OPTIONS = {
  animation: false,
  responsive: true,
  title: {
    display: true,
    text: 'Issues over time',
  },
  tooltips: {
    mode: 'x',
    intersect: false,
  },
  hover: {
    mode: 'x',
    intersect: false,
  },
  legend: {
    display: true,
    labels: {
      boxWidth: 15,
    },
  },
  scales: {
    xAxes: [{
      display: true,
      type: 'time',
      time: {parser: 'MM/DD/YYYY', tooltipFormat: 'll'},
      scaleLabel: {
        display: true,
        labelString: 'Day',
      },
    }],
    yAxes: [{
      display: true,
      ticks: {
        beginAtZero: true,
      },
      scaleLabel: {
        display: true,
        labelString: 'Value',
      },
    }],
  },
};
const COLOR_CHOICES = ['#00838F', '#B71C1C', '#2E7D32', '#00659C',
  '#5D4037', '#558B2F', '#FF6F00', '#6A1B9A', '#880E4F', '#827717'];
const BG_COLOR_CHOICES = ['#B2EBF2', '#EF9A9A', '#C8E6C9', '#B2DFDB',
  '#D7CCC8', '#DCEDC8', '#FFECB3', '#E1BEE7', '#F8BBD0', '#E6EE9C'];

/**
 * Set of serialized state this element should update for.
 * mr-app lowercases all query parameters before putting into store.
 * @type {Set<string>}
 */
export const subscribedQuery = new Set([
  'start-date',
  'end-date',
  'groupby',
  'labelprefix',
  'q',
  'can',
]);

const queryParamsHaveChanged = createObjectComparisonFunc(subscribedQuery);

/**
 * Mapping between query param's groupby value and chart application data.
 * @type {Object}
 */
const groupByMapping = {
  'open': {display: 'Is open', value: 'open'},
  'owner': {display: 'Owner', value: 'owner'},
  'comonent': {display: 'Component', value: 'component'},
  'status': {display: 'Status', value: 'status'},
};

/**
 * `<mr-chart>`
 *
 * Component rendering the chart view
 *
 */
export default class MrChart extends LitElement {
  /** @override */
  static get styles() {
    return css`
      :host {
        display: block;
        max-width: 800px;
        margin: 0 auto;
      }
      chops-chart {
        max-width: 100%;
      }
      div#options {
        max-width: 720px;
        margin: 2em auto;
        text-align: center;
      }
      div#options #unsupported-fields {
        font-weight: bold;
        color: orange;
      }
      div.align {
        display: flex;
      }
      div.align #frequency, div.align #groupBy {
        display: inline-block;
        width: 40%;
      }
      div.align #frequency #two-toggle {
        font-size: 95%;
        text-align: center;
        margin-bottom: 5px;
      }
      div.align #time, div.align #prediction {
        display: inline-block;
        width: 60%;
      }
      #dropdown {
        height: 50%;
      }
      div.section {
        display: inline-block;
        text-align: center;
      }
      div.section.input {
        padding: 4px 10px;
      }
      .menu {
        min-width: 50%;
        text-align: left;
        font-size: 12px;
        box-sizing: border-box;
        text-decoration: none;
        white-space: nowrap;
        padding: 0.25em 8px;
        transition: 0.2s background ease-in-out;
        cursor: pointer;
        color: var(--chops-link-color);
      }
      .menu:hover {
        background: hsl(0, 0%, 90%);
      }
      .choice.transparent {
        background: var(--chops-white);
        border-color: var(--chops-choice-color);
        border-radius: 4px;
      }
      .choice.shown {
        background: var(--chops-active-choice-bg);
      }
      .choice {
        padding: 4px 10px;
        background: var(--chops-choice-bg);
        color: var(--chops-choice-color);
        text-decoration: none;
        display: inline-block;
      }
      .choice.checked {
        background: var(--chops-active-choice-bg);
      }
      p .warning-message {
        display: none;
        font-size: 1.25em;
        padding: 0.25em;
        background-color: var(--chops-orange-50);
      }
      progress {
        background-color: var(--chops-white);
        border: 1px solid var(--chops-gray-500);
        margin: 0 0 1em;
        width: 100%;
        visibility: visible;
      }
      ::-webkit-progress-bar {
        background-color: var(--chops-white);
      }
      progress::-webkit-progress-value {
        transition: width 1s;
        background-color: #00838F;
      }
    `;
  }

  /** @override */
  updated(changedProperties) {
    if (changedProperties.has('queryParams')) {
      this._setPropsFromQueryParams();
      this._fetchData();
    }
  }

  /** @override */
  render() {
    const doneLoading = this.progress === 1;
    return html`
      <chops-chart
        type="line"
        .options=${CHART_OPTIONS}
        .data=${this._chartData(this.indices, this.values)}
      ></chops-chart>
      <div id="options">
        <p id="unsupported-fields">
          ${this.unsupportedFields.length ? `
            Unsupported fields: ${this.unsupportedFields.join(', ')}`: ''}
        </p>
        <progress
          value=${this.progress}
          ?hidden=${doneLoading}
        >Loading chart...</progress>
        <p class="warning-message" ?hidden=${!this.searchLimitReached}>
          Note: Some results are not being counted.
          Please narrow your query.
        </p>
        <p class="warning-message" ?hidden=${!this.maxQuerySizeReached}>
          Your query is too long.
          Showing ${MAX_QUERY_SIZE} weeks from end date.
        </p>
        <p class="warning-message" ?hidden=${!this.dateRangeNotLegal}>
          Your requested date range does not exist.
          Showing ${MAX_QUERY_SIZE} days from end date.
        </p>
        <p class="warning-message" ?hidden=${!this.cannedQueryOpen}>
          Your query scope prevents closed issues from showing.
        </p>
        <div class="align">
          <div id="frequency">
            <label for="two-toggle">Choose date range:</label>
            <div id="two-toggle">
              <chops-button @click="${this._setDateRange.bind(this, 180)}"
                class="${this.dateRange === 180 ? 'choice checked': 'choice'}">
                180 Days
              </chops-button>
              <chops-button @click="${this._setDateRange.bind(this, 90)}"
                class="${this.dateRange === 90 ? 'choice checked': 'choice'}">
                90 Days
              </chops-button>
              <chops-button @click="${this._setDateRange.bind(this, 30)}"
                class="${this.dateRange === 30 ? 'choice checked': 'choice'}">
                30 Days
              </chops-button>
            </div>
          </div>
          <div id="time">
            <label for="start-date">Choose start and end date:</label>
            <br />
            <input
              type="date"
              id="start-date"
              name="start-date"
              .value=${this.startDate && this.startDate.toISOString().substr(0, 10)}
              ?disabled=${!doneLoading}
              @change=${(e) => this.startDate = MrChart.dateStringToDate(e.target.value)}
            />
            <input
              type="date"
              id="end-date"
              name="end-date"
              .value=${this.endDate && this.endDate.toISOString().substr(0, 10)}
              ?disabled=${!doneLoading}
              @change=${(e) => this.endDate = MrChart.dateStringToDate(e.target.value)}
            />
            <chops-button @click="${this._onDateChanged}" class=choice>
              Apply
            </chops-button>
          </div>
        </div>
        <div class="align">
          <div id="prediction">
          <label for="two-toggle">Choose prediction range:</label>
          <div id="two-toggle">
            ${this._renderPredictChoice('Future Month', predRangeType.NEXT_MONTH)}
            ${this._renderPredictChoice('Future Quarter', predRangeType.NEXT_QUARTER)}
            ${this._renderPredictChoice('Future 50%', predRangeType.NEXT_50)}
            ${this._renderPredictChoice('Hide', predRangeType.HIDE)}
          </div>
        </div>
          <div id="groupBy">
            <label for="dropdown">Choose group by:</label>
            <mr-dropdown
              id="dropdown"
              ?disabled=${!doneLoading}
              .text=${this.groupBy.display}
            >
              ${this.dropdownHTML}
            </mr-dropdown>
          </div>
        </div>
      </div>
    `;
  }

  /**
   * Renders a single prediction button.
   * @param {string} choiceName The text displayed on the button.
   * @param {number} rangeType An enum-like number specifying which range
   *   to use.
   * @return {TemplateResult}
   */
  _renderPredictChoice(choiceName, rangeType) {
    const changePrediction = (_e) => {
      this.predRange = rangeType;
      this._fetchData();
    };
    return html`
      <chops-button
        @click=${changePrediction}
        class="${this.predRange === rangeType ? 'checked': ''} choice">
        ${choiceName}
      </chops-button>
    `;
  }

  /** @override */
  static get properties() {
    return {
      progress: {type: Number},
      projectName: {type: String},
      hotlistId: {type: Number},
      indices: {type: Array},
      values: {type: Array},
      unsupportedFields: {type: Array},
      dateRangeNotLegal: {type: Boolean},
      dateRange: {type: Number},
      frequency: {type: Number},
      queryParams: {
        type: Object,
        hasChanged: queryParamsHaveChanged,
      },
    };
  }

  /** @override */
  constructor() {
    super();
    this.progress = 0.05;
    this.values = [];
    this.indices = [];
    this.unsupportedFields = [];
    this.predRange = predRangeType.HIDE;
    this._page = page;
  }

  /** @override */
  connectedCallback() {
    super.connectedCallback();

    if (!this.projectName && !this.hotlistId) {
      throw new Error('Attribute `projectName` or `hotlistId` required.');
    }
    this._setPropsFromQueryParams();
    this._constructDropdownMenu();
  }

  /**
   * Initialize queryParams and set properties from the queryParams.
   * Since this page exists in both the SPA and ezt they initialize mr-chart
   * differently, ie in ezt, this.queryParams will be undefined during
   * connectedCallback. Until ezt is deleted, initialize props here.
   */
  _setPropsFromQueryParams() {
    if (!this.queryParams) {
      const params = qs.parse(document.location.search.substring(1));
      // ezt pages used querystring as source of truth
      // and 'labelPrefix'in query param, but SPA uses
      // redux store's sitewide.queryParams as source of truth
      // and lowercases all keys in sitewide.queryParams
      if (params.hasOwnProperty('labelPrefix')) {
        const labelPrefixValue = params['labelPrefix'];
        params['labelprefix'] = labelPrefixValue;
        delete params['labelPrefix'];
      }
      this.queryParams = params;
    }
    this.endDate = MrChart.getEndDate(this.queryParams['end-date']);
    this.startDate = MrChart.getStartDate(
        this.queryParams['start-date'],
        this.endDate, DEFAULT_NUM_DAYS);
    this.groupBy = MrChart.getGroupByFromQuery(this.queryParams);
  }

  /**
   * Set dropdown options menu in HTML.
   */
  async _constructDropdownMenu() {
    const response = await this._getLabelPrefixes();
    let dropdownOptions = ['None', 'Component', 'Is open', 'Status', 'Owner'];
    dropdownOptions = dropdownOptions.concat(response);
    const dropdownHTML = dropdownOptions.map((str) => html`
      <option class='menu' @click=${this._setGroupBy}>
        ${str}</option>`);
    this.dropdownHTML = html`${dropdownHTML}`;
  }

  /**
   * Call global page.js to change frontend route based on new parameters
   * @param {Object<string, string>} newParams
   */
  _changeUrlParams(newParams) {
    const newUrl = urlWithNewParams(`/p/${this.projectName}/issues/list`,
        this.queryParams, newParams);
    this._page(newUrl);
  }

  /**
   * Set start date and end date and trigger url action
   */
  _onDateChanged() {
    const newParams = {
      'start-date': this.startDate.toISOString().substr(0, 10),
      'end-date': this.endDate.toISOString().substr(0, 10),
    };
    this._changeUrlParams(newParams);
  }

  /**
   * Fetch data required to render chart
   * @fires Event#allDataLoaded
   */
  async _fetchData() {
    this.dateRange = Math.ceil(
        (this.endDate - this.startDate) / (1000 * SECONDS_IN_DAY));

    // Coordinate different params and flags, protect against illegal queries
    // Case for start date greater than end date.
    if (this.dateRange <= 0) {
      this.frequency = 7;
      this.dateRangeNotLegal = true;
      this.maxQuerySizeReached = false;
      this.dateRange = MAX_QUERY_SIZE;
    } else {
      this.dateRangeNotLegal = false;
      if (this.dateRange >= MAX_QUERY_SIZE * 7) {
        // Case for date range too long, requires >= MAX_QUERY_SIZE queries.
        this.frequency = 7;
        this.maxQuerySizeReached = true;
        this.dateRange = MAX_QUERY_SIZE * 7;
      } else {
        this.maxQuerySizeReached = false;
        if (this.dateRange < MAX_QUERY_SIZE) {
          // Case for small date range, displayed in daily frequency.
          this.frequency = 1;
        } else {
          // Case for medium date range, displayed in weekly frequency.
          this.frequency = 7;
        }
      }
    }
    // Set canned query flag.
    this.cannedQueryOpen = (this.queryParams.can === '2' &&
      this.groupBy.value === 'open');

    // Reset chart variables except indices.
    this.progress = 0.05;

    let numTimestampsLoaded = 0;
    const timestampsChronological = MrChart.makeTimestamps(this.endDate,
        this.frequency, this.dateRange);
    const tsToIndexMap = new Map(timestampsChronological.map((ts, idx) => (
      [ts, idx]
    )));
    this.indices = MrChart.makeIndices(timestampsChronological);
    const timestamps = MrChart.sortInBisectOrder(timestampsChronological);
    this.values = new Array(timestamps.length).fill(undefined);

    const fetchPromises = timestamps.map(async (ts) => {
      const data = await this._fetchDataAtTimestamp(ts);
      const index = tsToIndexMap.get(ts);
      this.values[index] = data.issues;
      numTimestampsLoaded += 1;
      const progressValue = numTimestampsLoaded / timestamps.length;
      this.progress = progressValue;

      return data;
    });

    const chartData = await Promise.all(fetchPromises);

    // This is purely for testing purposes
    this.dispatchEvent(new Event('allDataLoaded'));

    // Check if the query includes any field values that are not supported.
    const flatUnsupportedFields = chartData.reduce((acc, datum) => {
      if (datum.unsupportedField) {
        acc = acc.concat(datum.unsupportedField);
      }
      return acc;
    }, []);
    this.unsupportedFields = Array.from(new Set(flatUnsupportedFields));

    this.searchLimitReached = chartData.some((d) => d.searchLimitReached);
  }

  /**
   * fetch data at timestamp
   * @param {number} timestamp
   * @return {{date: number, issues: Array<Map.<string, number>>,
   *   unsupportedField: string, searchLimitReached: string}}
   */
  async _fetchDataAtTimestamp(timestamp) {
    const query = this.queryParams.q;
    const cannedQuery = this.queryParams.can;
    const message = {
      timestamp: timestamp,
      projectName: this.projectName,
      query: query,
      cannedQuery: cannedQuery,
      hotlistId: this.hotlistId,
      groupBy: undefined,
    };
    if (this.groupBy.value !== '') {
      message['groupBy'] = this.groupBy.value;
      if (this.groupBy.value === 'label') {
        message['labelPrefix'] = this.groupBy.labelPrefix;
      }
    }
    const response = await prpcClient.call('monorail.Issues',
        'IssueSnapshot', message);

    let issues;
    if (response.snapshotCount) {
      issues = response.snapshotCount.reduce((map, curr) => {
        if (curr.dimension !== undefined) {
          if (this.groupBy.value === '') {
            map.set('Issue Count', curr.count);
          } else {
            map.set(curr.dimension, curr.count);
          }
        }
        return map;
      }, new Map());
    } else {
      issues = new Map();
    }
    return {
      date: timestamp * 1000,
      issues: issues,
      unsupportedField: response.unsupportedField,
      searchLimitReached: response.searchLimitReached,
    };
  }

  /**
   * Get prefixes from the set of labels.
   */
  async _getLabelPrefixes() {
    // If no project (i.e. viewing a hotlist), return empty list.
    if (!this.projectName) {
      return [];
    }

    const projectRequestMessage = {
      project_name: this.projectName};
    const labelsResponse = await prpcClient.call(
        'monorail.Projects', 'GetLabelOptions', projectRequestMessage);
    const labelPrefixes = new Set();
    for (let i = 0; i < labelsResponse.labelOptions.length; i++) {
      const label = labelsResponse.labelOptions[i].label;
      if (label.includes('-')) {
        labelPrefixes.add(label.split('-')[0]);
      }
    }
    return Array.from(labelPrefixes);
  }

  /**
   * construct chart data
   * @param {Array} indices
   * @param {Array} values
   * @return {Object} chart data and options
   */
  _chartData(indices, values) {
    // Generate a map of each data line {dimension:string, value:array}
    const mapValues = new Map();
    for (let i = 0; i < values.length; i++) {
      if (values[i] !== undefined) {
        values[i].forEach((value, key, map) => mapValues.set(key, []));
      }
    }
    // Count the number of 0 or undefined data points.
    let count = 0;
    for (let i = 0; i < values.length; i++) {
      if (values[i] !== undefined) {
        if (values[i].size === 0) {
          count++;
        }
        // Set none-existing data points 0.
        mapValues.forEach((value, key, map) => {
          mapValues.set(key, value.concat([values[i].get(key) || 0]));
        });
      } else {
        count++;
      }
    }
    // Legend display set back to default.
    CHART_OPTIONS.legend.display = true;
    // Check if any positive valued data exist, if not, draw an array of zeros.
    if (count === values.length) {
      return {
        type: 'line',
        labels: indices,
        datasets: [{
          label: this.groupBy.labelPrefix,
          data: Array(indices.length).fill(0),
          backgroundColor: COLOR_CHOICES[0],
          borderColor: COLOR_CHOICES[0],
          showLine: true,
          fill: false,
        }],
      };
    }
    // Convert map to a dataset of lines.
    let arrayValues = [];
    mapValues.forEach((value, key, map) => {
      arrayValues.push({
        label: key,
        data: value,
        backgroundColor: COLOR_CHOICES[arrayValues.length %
          COLOR_CHOICES.length],
        borderColor: COLOR_CHOICES[arrayValues.length % COLOR_CHOICES.length],
        showLine: true,
        fill: false,
      });
    });
    arrayValues = MrChart.getSortedLines(arrayValues, MAX_DISPLAY_LINES);
    if (this.predRange === predRangeType.HIDE) {
      return {
        type: 'line',
        labels: indices,
        datasets: arrayValues,
      };
    }

    let predictedValues = [];
    let originalData;
    let predictedData;
    let maxData;
    let minData;
    let currColor;
    let currBGColor;
    // Check if displayed values > MAX_DISPLAY_LINES, hide legend.
    if (arrayValues.length * 4 > MAX_DISPLAY_LINES) {
      CHART_OPTIONS.legend.display = false;
    } else {
      CHART_OPTIONS.legend.display = true;
    }
    for (let i = 0; i < arrayValues.length; i++) {
      [originalData, predictedData, maxData, minData] =
        MrChart.getAllData(indices, arrayValues[i]['data'], this.dateRange,
            this.predRange, this.frequency, this.endDate);
      currColor = COLOR_CHOICES[i % COLOR_CHOICES.length];
      currBGColor = BG_COLOR_CHOICES[i % COLOR_CHOICES.length];
      predictedValues = predictedValues.concat([{
        label: arrayValues[i]['label'],
        backgroundColor: currColor,
        borderColor: currColor,
        data: originalData,
        showLine: true,
        fill: false,
      }, {
        label: arrayValues[i]['label'].concat(' prediction'),
        backgroundColor: currColor,
        borderColor: currColor,
        borderDash: [5, 5],
        data: predictedData,
        pointRadius: 0,
        showLine: true,
        fill: false,
      }, {
        label: arrayValues[i]['label'].concat(' lower error'),
        backgroundColor: currBGColor,
        borderColor: currBGColor,
        borderDash: [5, 5],
        data: minData,
        pointRadius: 0,
        showLine: true,
        hidden: true,
        fill: false,
      }, {
        label: arrayValues[i]['label'].concat(' upper error'),
        backgroundColor: currBGColor,
        borderColor: currBGColor,
        borderDash: [5, 5],
        data: maxData,
        pointRadius: 0,
        showLine: true,
        hidden: true,
        fill: '-1',
      }]);
    }
    return {
      type: 'scatter',
      datasets: predictedValues,
    };
  }

  /**
   * Change group by based on dropdown menu selection.
   * @param {Event} e
   */
  _setGroupBy(e) {
    switch (e.target.text) {
      case 'None':
        this.groupBy = {value: undefined};
        break;
      case 'Is open':
        this.groupBy = {value: 'open'};
        break;
      case 'Owner':
      case 'Component':
      case 'Status':
        this.groupBy = {value: e.target.text.toLowerCase()};
        break;
      default:
        this.groupBy = {value: 'label', labelPrefix: e.target.text};
    }
    this.groupBy['display'] = e.target.text;
    this.shadowRoot.querySelector('#dropdown').text = e.target.text;
    this.shadowRoot.querySelector('#dropdown').close();

    const newParams = {
      'groupby': this.groupBy.value,
      'labelprefix': this.groupBy.labelPrefix,
    };

    this._changeUrlParams(newParams);
  }

  /**
   * Change date range and frequency based on button clicked.
   * @param {number} dateRange Number of days in date range
   */
  _setDateRange(dateRange) {
    if (this.dateRange !== dateRange) {
      this.startDate = new Date(
          this.endDate.getTime() - 1000 * SECONDS_IN_DAY * dateRange);
      this._onDateChanged();
      window.getTSMonClient().recordDateRangeChange(dateRange);
    }
  }

  /**
   * Move first, last, and median to the beginning of the array, recursively.
   * @param  {Array} timestamps
   * @return {Array}
   */
  static sortInBisectOrder(timestamps) {
    const arr = [];
    if (timestamps.length === 0) {
      return arr;
    } else if (timestamps.length <= 2) {
      return timestamps;
    } else {
      const beginTs = timestamps.shift();
      const endTs = timestamps.pop();
      const medianTs = timestamps.splice(timestamps.length / 2, 1)[0];
      return [beginTs, endTs, medianTs].concat(
          MrChart.sortInBisectOrder(timestamps));
    }
  }

  /**
   * Populate array of timestamps we want to fetch.
   * @param {Date} endDate
   * @param {number} frequency
   * @param {number} numDays
   * @return {Array}
   */
  static makeTimestamps(endDate, frequency, numDays=DEFAULT_NUM_DAYS) {
    if (!endDate) {
      throw new Error('endDate required');
    }
    const endTimeSeconds = Math.round(endDate.getTime() / 1000);
    const timestampsChronological = [];
    for (let i = 0; i < numDays; i += frequency) {
      timestampsChronological.unshift(endTimeSeconds - (SECONDS_IN_DAY * i));
    }
    return timestampsChronological;
  }

  /**
   * Convert a string '2018-11-03' to a Date object.
   * @param  {string} dateString
   * @return {Date}
   */
  static dateStringToDate(dateString) {
    if (!dateString) {
      return null;
    }
    const splitDate = dateString.split('-');
    const year = Number.parseInt(splitDate[0]);
    // Month is 0-indexed, so subtract one.
    const month = Number.parseInt(splitDate[1]) - 1;
    const day = Number.parseInt(splitDate[2]);
    return new Date(Date.UTC(year, month, day, 23, 59, 59));
  }

  /**
   * Returns a Date parsed from string input, defaults to current date.
   * @param {string} input
   * @return {Date}
   */
  static getEndDate(input) {
    if (input) {
      const date = MrChart.dateStringToDate(input);
      if (date) {
        return date;
      }
    }
    const today = new Date();
    today.setHours(23);
    today.setMinutes(59);
    today.setSeconds(59);
    return today;
  }

  /**
   * Return a Date parsed from string input
   * defaults to diff days befores endDate
   * @param {string} input
   * @param {Date} endDate
   * @param {number} diff
   * @return {Date}
   */
  static getStartDate(input, endDate, diff) {
    if (input) {
      const date = MrChart.dateStringToDate(input);
      if (date) {
        return date;
      }
    }
    return new Date(endDate.getTime() - 1000 * SECONDS_IN_DAY * diff);
  }

  /**
   * Make indices
   * @param {Array} timestamps
   * @return {Array}
   */
  static makeIndices(timestamps) {
    const dateFormat = {year: 'numeric', month: 'numeric', day: 'numeric'};
    return timestamps.map((ts) => (
      (new Date(ts * 1000)).toLocaleDateString('en-US', dateFormat)
    ));
  }

  /**
   * Generate predicted future data based on previous data.
   * @param {Array} values
   * @param {number} dateRange
   * @param {number} interval
   * @param {number} frequency
   * @param {Date} inputEndDate
   * @return {Array}
   */
  static getPredictedData(
      values, dateRange, interval, frequency, inputEndDate) {
    // TODO(weihanl): changes to support frequencies other than 1 and 7.
    let n;
    let endDateRange;
    if (frequency === 1) {
      // Display in daily.
      n = values.length;
      endDateRange = interval;
    } else {
      // Display in weekly.
      n = Math.floor((DEFAULT_NUM_DAYS + 1) / 7);
      endDateRange = interval * 7 - 1;
    }
    const [slope, intercept] = linearRegression(values, n);
    const endDate = new Date(inputEndDate.getTime() +
        1000 * SECONDS_IN_DAY * (1 + endDateRange));
    const timestampsChronological = MrChart.makeTimestamps(
        endDate, frequency, endDateRange);
    const predictedIndices = MrChart.makeIndices(timestampsChronological);

    // Obtain future data and past data on the generated line.
    const predictedValues = [];
    const generatedValues = [];
    for (let i = 0; i < interval; i++) {
      predictedValues.push(Math.round(100*((i + n) * slope + intercept)) / 100);
    }
    for (let i = 0; i < n; i++) {
      generatedValues.push(Math.round(100*(i * slope + intercept)) / 100);
    }
    return [predictedIndices, predictedValues, generatedValues];
  }

  /**
   * Generate error range lines using +/- standard error
   * on intercept to original line.
   * @param {Array} generatedValues
   * @param {Array} values
   * @param {Array} predictedValues
   * @return {Array}
   */
  static getErrorData(generatedValues, values, predictedValues) {
    const diffs = [];
    for (let i = 0; i < generatedValues.length; i++) {
      diffs.push(values[values.length - generatedValues.length + i] -
          generatedValues[i]);
    }
    const sqDiffs = diffs.map((v) => v * v);
    const stdDev = sqDiffs.reduce((sum, v) => sum + v) / values.length;
    const maxValues = predictedValues.map(
        (x) => Math.round(100 * (x + stdDev)) / 100);
    const minValues = predictedValues.map(
        (x) => Math.round(100 * (x - stdDev)) / 100);
    return [maxValues, minValues];
  }

  /**
   * Format all data using scattered dot representation for a single chart line.
   * @param {Array} indices
   * @param {Array} values
   * @param {humber} dateRange
   * @param {number} predRange
   * @param {number} frequency
   * @param {Date} endDate
   * @return {Array}
   */
  static getAllData(indices, values, dateRange, predRange, frequency, endDate) {
    // Set the number of data points that needs to be generated based on
    // future time range and frequency.
    let interval;
    switch (predRange) {
      case predRangeType.NEXT_MONTH:
        interval = frequency === 1 ? 30 : 4;
        break;
      case predRangeType.NEXT_QUARTER:
        interval = frequency === 1 ? 90 : 13;
        break;
      case predRangeType.NEXT_50:
        interval = Math.floor((dateRange + 1) / (frequency * 2));
        break;
    }

    const [predictedIndices, predictedValues, generatedValues] =
      MrChart.getPredictedData(values, dateRange, interval, frequency, endDate);
    const [maxValues, minValues] =
      MrChart.getErrorData(generatedValues, values, predictedValues);
    const n = generatedValues.length;

    // Format data into an array of {x:"MM/DD/YYYY", y:1.00} to draw chart.
    const originalData = [];
    const predictedData = [];
    const maxData = [{
      x: indices[values.length - 1],
      y: generatedValues[n - 1],
    }];
    const minData = [{
      x: indices[values.length - 1],
      y: generatedValues[n - 1],
    }];
    for (let i = 0; i < values.length; i++) {
      originalData.push({x: indices[i], y: values[i]});
    }
    for (let i = 0; i < n; i++) {
      predictedData.push({x: indices[values.length - n + i],
        y: Math.max(Math.round(100 * generatedValues[i]) / 100, 0)});
    }
    for (let i = 0; i < predictedValues.length; i++) {
      predictedData.push({
        x: predictedIndices[i],
        y: Math.max(predictedValues[i], 0),
      });
      maxData.push({x: predictedIndices[i], y: Math.max(maxValues[i], 0)});
      minData.push({x: predictedIndices[i], y: Math.max(minValues[i], 0)});
    }
    return [originalData, predictedData, maxData, minData];
  }

  /**
   * Sort lines by data in reversed chronological order and
   * return top n lines with most issues.
   * @param {Array} arrayValues
   * @param {number} index
   * @return {Array}
   */
  static getSortedLines(arrayValues, index) {
    if (index >= arrayValues.length) {
      return arrayValues;
    }
    // Convert data by reversing and starting from last digit and sort
    // according to the resulting value. e.g. [4,2,0] => 24, [0,4,3] => 340
    const sortedValues = arrayValues.slice().sort((arrX, arrY) => {
      const intX = parseInt(
          arrX.data.map((i) => i.toString()).reverse().join(''));
      const intY = parseInt(
          arrY.data.map((i) => i.toString()).reverse().join(''));
      return intY - intX;
    });
    return sortedValues.slice(0, index);
  }

  /**
   * Parses queryParams for groupBy property
   * @param {Object<string, string>} queryParams
   * @return {Object<string, string>}
   */
  static getGroupByFromQuery(queryParams) {
    const defaultValue = {display: 'None', value: ''};

    const labelMapping = {
      'label': {
        display: queryParams.labelprefix,
        value: 'label',
        labelPrefix: queryParams.labelprefix,
      },
    };

    return groupByMapping[queryParams.groupby] ||
        labelMapping[queryParams.groupby] ||
        defaultValue;
  }
}

customElements.define('mr-chart', MrChart);
