// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

import {
  VIEW_BY_INSTANCE_TYPE,
  VIEW_BY_INSTANCE_CATEGORY,
  VIEW_BY_FIELD_TYPE
} from './details-selection.js';

defineCustomElement('histogram-viewer', (templateText) =>
 class HistogramViewer extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = templateText;
  }

  $(id) {
    return this.shadowRoot.querySelector(id);
  }

  set data(value) {
    this._data = value;
    this.stateChanged();
  }

  get data() {
    return this._data;
  }

  set selection(value) {
    this._selection = value;
    this.stateChanged();
  }

  get selection() {
    return this._selection;
  }

  isValid() {
    return this.data && this.selection &&
           (this.selection.data_view === VIEW_BY_INSTANCE_CATEGORY ||
            this.selection.data_view === VIEW_BY_INSTANCE_TYPE);
    ;
  }

  hide() {
    this.$('#container').style.display = 'none';
  }

  show() {
    this.$('#container').style.display = 'block';
  }

  getOverallValue() {
    switch (this.selection.data_view) {
      case VIEW_BY_FIELD_TYPE:
        return NaN;
      case VIEW_BY_INSTANCE_CATEGORY:
        return this.getPropertyForCategory('overall');
      case VIEW_BY_INSTANCE_TYPE:
      default:
        return this.getPropertyForInstanceTypes('overall');
    }
  }

  stateChanged() {
    if (this.isValid()) {
      const overall_bytes = this.getOverallValue();
      this.$('#overall').innerHTML = `Overall: ${overall_bytes / KB} KB`;
      this.drawChart();
    } else {
      this.hide();
    }
  }

  get selectedData() {
    console.assert(this.data, 'invalid data');
    console.assert(this.selection, 'invalid selection');
    return this.data[this.selection.isolate]
        .gcs[this.selection.gc][this.selection.data_set];
  }

  get selectedInstanceTypes() {
    console.assert(this.selection, 'invalid selection');
    return Object.values(this.selection.categories)
        .reduce((accu, current) => accu.concat(current), []);
  }

  getPropertyForCategory(property) {
    return Object.values(this.selection.categories)
        .reduce(
            (outer_accu, instance_types) => outer_accu +
                instance_types.reduce(
                    (inner_accu, instance_type) => inner_accu +
                        this.selectedData
                            .instance_type_data[instance_type][property],
                    0),
            0);
  }

  getPropertyForInstanceTypes(property) {
    return this.selectedInstanceTypes.reduce(
        (accu, instance_type) => accu +
            this.selectedData.instance_type_data[instance_type][property],
        0);
  }

  formatBytes(bytes) {
    const units = ['B', 'KiB', 'MiB'];
    const divisor = 1024;
    let index = 0;
    while (index < units.length && bytes >= divisor) {
      index++;
      bytes /= divisor;
    }
    return bytes + units[index];
  }

  getCategoryData() {
    const labels = [
      'Bucket',
      ...Object.keys(this.selection.categories)
          .map(k => this.selection.category_names.get(k))
    ];
    const data = this.selectedData.bucket_sizes.map(
        (bucket_size, index) =>
            [`<${this.formatBytes(bucket_size)}`,
             ...Object.values(this.selection.categories)
                 .map(
                     instance_types =>
                         instance_types
                             .map(
                                 instance_type =>
                                     this.selectedData
                                         .instance_type_data[instance_type]
                                         .histogram[index])
                             .reduce((accu, current) => accu + current, 0))]);
    // Adjust last histogram bucket label.
    data[data.length - 1][0] = 'rest';
    return [labels, ...data];
  }

  getInstanceTypeData() {
    const instance_types = this.selectedInstanceTypes;
    const labels = ['Bucket', ...instance_types];
    const data = this.selectedData.bucket_sizes.map(
        (bucket_size, index) =>
            [`<${bucket_size}`,
             ...instance_types.map(
                 instance_type =>
                     this.selectedData.instance_type_data[instance_type]
                         .histogram[index])]);
    // Adjust last histogram bucket label.
    data[data.length - 1][0] = 'rest';
    return [labels, ...data];
  }

  getChartData() {
    switch (this.selection.data_view) {
      case VIEW_BY_FIELD_TYPE:
        return this.getFieldData();
      case VIEW_BY_INSTANCE_CATEGORY:
        return this.getCategoryData();
      case VIEW_BY_INSTANCE_TYPE:
      default:
        return this.getInstanceTypeData();
    }
  }

  drawChart() {
    const chart_data = this.getChartData();
    const data = google.visualization.arrayToDataTable(chart_data);
    const options = {
      legend: {position: 'top', maxLines: '1'},
      chartArea: {width: '85%', height: '85%'},
      bar: {groupWidth: '80%'},
      hAxis: {
        title: 'Count',
        minValue: 0
      },
      explorer: {},
    };
    const chart = new google.visualization.BarChart(this.$('#chart'));
    this.show();
    chart.draw(data, options);
  }
});
