import {
  COMPONENT_MODE_EMPTY,
  COMPONENT_MODE_ERROR,
  COMPONENT_MODE_INITIAL,
  COMPONENT_MODE_LOADING,
  COMPONENT_MODE_OK,
  ComponentModeWindow,
  MmuiCommonComponent,
  MmuiProps,
  MmuiState,
} from './common';
import * as React from 'react';

import vegaEmbed from 'vega-embed';

export interface MmuiChartVegaProps extends MmuiProps {
  chartId: string; // html element selector of the chart container
  chartSpec: any; // chart configuration, including selector, xScale, yScale, axis config, etc, could be different for each type of chart
  chartEmbedOpts: any;
  payload?: any; // received from the server, includes data, whether data hasError, isInvalidated, etc
  reportIssueUrl?: string; // url link to report issue when something goes wrong
}

export class MmuiChartVegaComponent<
  P extends MmuiChartVegaProps,
  S extends MmuiState
> extends MmuiCommonComponent<P, S> {
  getChartSpec(fromStore = false) {
    let chartSpec = this.props.chartSpec;
    if (fromStore || this.useStore) {
      chartSpec = this.props.store.component[this.name]?.chartSpec;
    }

    return chartSpec;
  }

  getChartEmbedOpts(fromStore = false) {
    let chartEmbedOpts = this.props.chartEmbedOpts;
    if (fromStore || this.useStore) {
      chartEmbedOpts = this.props.store.component[this.name]?.chartEmbedOpts;
    }

    return chartEmbedOpts;
  }

  buildChart(dataArray) {
    const chartSpec = this.getChartSpec(),
      chartEmbedOpts = this.getChartEmbedOpts();
    chartSpec.data.values = dataArray;
    vegaEmbed(`#${this.props.chartId}`, chartSpec, chartEmbedOpts);
  }

  /**
   * Extract the dataArray portion of the payload received from the server.
   * @param payload
   */
  extractDataArray(payload) {
    let dataArray = [];

    if (payload && payload.data) {
      dataArray = payload.data;
    }

    return dataArray;
  }

  /**
   * Get Component mode based on data payload
   */
  getComponentMode(payload) {
    let mode = COMPONENT_MODE_INITIAL,
      dataArray,
      hasData = false;
    if (payload) {
      if (payload.hasError) {
        mode = COMPONENT_MODE_ERROR;
      } else if (payload.isInvalidated) {
        mode = COMPONENT_MODE_LOADING;
      } else {
        dataArray = this.extractDataArray(payload);
        hasData = dataArray.length > 0;
        if (hasData) {
          mode = COMPONENT_MODE_OK;
        } else {
          mode = COMPONENT_MODE_EMPTY;
        }
      }
    }

    return mode;
  }

  componentDidMount() {
    const payload = this.getPayloadData();
    const a_la_mode = this.getComponentMode(payload);
    if (a_la_mode == COMPONENT_MODE_OK) {
      const dataArray = this.extractDataArray(payload);
      this.buildChart(dataArray);
    }
  }

  /**
   * On update to Component props or state
   */
  componentDidUpdate() {
    const payload = this.getPayloadData();
    const a_la_mode = this.getComponentMode(payload);
    if (a_la_mode == COMPONENT_MODE_OK) {
      const dataArray = this.extractDataArray(payload);
      this.buildChart(dataArray);
    }
  }

  /**
   * Render the Chart Component
   */

  render() {
    const payload = this.getPayloadData();
    const a_la_mode = this.getComponentMode(payload);
    let chartContent = null;
    if (a_la_mode == COMPONENT_MODE_OK) {
      chartContent = (
        <div className="chart-panel-body">
          <div id={this.props.chartId} className="chart"></div>
        </div>
      );
    }
    return (
      <React.Fragment>
        {chartContent}
        <ComponentModeWindow
          mode={a_la_mode}
          reportIssueUrl={this.props.reportIssueUrl}
          loadingGraphicUrl={this.loadingImage}
          hasEmptyMode={true}
          hasErrorMode={true}
        />
      </React.Fragment>
    );
  }
}
