import {Graph} from './graph';
import {EmptyGraph} from "./emptygraph";
import {SingleGraph} from "./singlegraph";
import {MultiGraph} from "./multigraph";

declare var require: any



export class GraphLoader {
  static customSize = -1;
  static width = 800;
  static height = 300;
  static lastGraphView;

  static setSize(width : number, height : number) {
    this.width = width;
    this.height = height;
  }

  /**
   * Loads graph with default interval value (e.g. for observation service)
   * @param sensors array of sensors to display
   * @param data source of values for vega graph
   * @param legendInfo source of legend info for graph (e.g. sensor phenomenon)
   * @param element name of html element for graph display
   * @param isAnalytics true/false analytics/observations
   */
  static getGraph(sensors, data, legendInfo, element, isAnalytics) {
    return this.getGraphWithInterval(sensors, data, 1800000, legendInfo, element, isAnalytics);
  }



  /**
   * Loads graph with specified interval (e.g. for analytics service)
   * @param sensors array of sensors to display
   * @param data source of values for vega graph
   * @param interval default graph interval used for different purposes (in milliseconds) (see timeWindow and maxTimeDifference in vega specification)
   * @param legendInfo source of legend info for graph (e.g. sensor phenomenon)
   * @param element name of html element for graph display
   * @param isAnalytics true/false analytics/observations
   */
  static getGraphWithInterval(sensors, data, interval, legendInfo, element, isAnalytics) {
    // gets uses sensors array to get graph type
    // then gets configuration and specification from corresponding class
    const graph = this.getGraphType(sensors,data, interval, legendInfo, isAnalytics);
    const config = graph.getConfig();
    const spec = graph.getSpec();

   // then displays the graph
    return this.showGraph(spec, config, element);
  }


  /**
   * Create graph of specific type according to selected sensors
   * @param sensors array of sensors to display
   * @param data source of values for vega graph
   * @param interval default graph interval used for different purposes (in milliseconds) (see timeWindow and maxTimeDifference in vega specification)
   * @param legendInfo source of legend info for graph (e.g. sensor phenomenon)
   * @param isAnalytics isAnalytics true/false analytics/observations
   */
  static getGraphType(sensors, data, interval, legendInfo, isAnalytics): Graph {
    if (sensors == null) {
      return new EmptyGraph('No sensors selected.');

    }  else if (Array.isArray(sensors)) {
      if (sensors.length === 0) {
        return new EmptyGraph('No sensors selected.');
      } else if (sensors.length === 1) {
        return new SingleGraph(sensors[0], isAnalytics, data, legendInfo,interval);
      } else {
        return new MultiGraph(isAnalytics, data, legendInfo,interval);
      }

    } else {
      return new SingleGraph(sensors, isAnalytics, data, legendInfo, interval);
    }
  }



  /**
   * Displays the graph
   * @param spec vega specification
   * @param config vega configuration
   * @param element name of html element for graph display
   */
  static showGraph(spec, config, element) {
    const vega = require('vega');
    const vegaTooltip = require('vega-tooltip');
    const handler = new vegaTooltip.Handler();

    config.width = this.width;
    config.height = this.height;

    // --- LOGGING THE SOURCE CODE ---
    const fullSpecForExport = {
      ...spec,
      config
    };

    console.log('COPY THIS INTO VEGA EDITOR:');
    console.log(JSON.stringify(fullSpecForExport, null, 2));

    // --------------------------------

    return new vega.View(vega.parse(spec, config))
      .tooltip(handler.call)
      .initialize(element)
      .hover()
      .runAsync();
  }

  static ResizeGraph(graphView, newWidth: number) {
    graphView.width(newWidth).height(300).runAsync();
    console.log('Requested width : ', newWidth);
    console.log('Got width: ', graphView.width());

    // check if Vega "stole" pixels. If it did, force it again.
    /*
    if (graphView.width() < newWidth - 50) {
      graphView.width(newWidth).height(300).runAsync();
      console.log('Calling resize twice');
    }
     */
  }

  static ChangeYRange(graphView, newMin: number, newMax: number) {
    graphView.signal('extMin', newMin);
    graphView.signal('extMax', newMax);
    return graphView.runAsync();
  }
}
