/* globals Twitch, uuid */

let lazyEvents = window.lazyEvents = [];

// Helpers
function getTimeAsFloat(time) {
  if (time) {
    return time / 1000;
  }
  return (new Date().getTime() / 1000);
}

// We always track the event on both spade and mixpanel
const { funnel: { debugEnabled } } = Twitch.tracking;

// Benchmark public methods
export default {
  // Set a flag for whether this is the first time the page has been loaded
  _firstPageLoad: true,

  // Tracks an `init` event using `benchmark.track`
  _init() {
    this.end(); // End any current sessions if we have them
    this.start(); // Start a new session

    let timing = window.performance.timing;
    this.track('fetch_start', { client_time: getTimeAsFloat(timing.fetchStart) });

    if (window.INIT_BENCHMARK_TIMESTAMP) {
      this.track('init', { client_time: getTimeAsFloat(window.INIT_BENCHMARK_TIMESTAMP) });
    }
  },

  /**
   * Starts a new session and fires a `transition` event
   * Valid phase names:
   *  - validate: Indicates we are validating a transition (beforeModel/model/afterModel hooks)
   *  - execute: Indicates we are executing a transition (activate/setupController/renderTemplate hooks)
   * TODO: Evaluate whether we want to start/end sessions in this way long-term
   */
  transition(phase = 'execute', properties = {}) {
    this.start();
    this.track(`${phase}_transition`, properties);
  },

  /**
   * Begin a new session if one does not exist yet
   * Generates and stores a UUID for the new benchmarking session
   */
  start() {
    if (!this.getSession()) {
      Twitch.storage.set('benchmark_id', uuid(), { storage: 'sessionStorage' });
    }
  },

  // Ends the current benchmarking session. This allows a subsequent benchmarking session to begin afterwards.
  end() {
    Twitch.storage.del('benchmark_id', { storage: 'sessionStorage' });
  },

  // Returns the current benchmark session
  getSession() {
    return Twitch.storage.get('benchmark_id', { storage: 'sessionStorage' });
  },

  // Calls the correct method on `Twitch.tracking` and propagates the event to mixpanel and spade.
  // Includes the current benchmark session and the current time.
  //
  // @param {string} name - The event in mixpanel/spade will be prepended with 'benchmark'
  //     e.g. 'init' => 'benchmark_init'
  //
  // @param {object} data - An object with additional parameters to pass to spade/mixpanel
  //
  track(name, data = {}) {
    // Add the current timestamp and benchmark session_id if one was not already passed in
    data.client_time = data.client_time || getTimeAsFloat();
    data.benchmark_session_id = data.benchmark_session_id || this.getSession();

    let event = `benchmark_${name}`;

    lazyEvents.push({ services: ['spade'], event, data });

    if (window.lazyEventsFlush) {
      window.lazyEventsFlush();
    }

    if (debugEnabled()) {
      console.log(`Tracked: ${event} with the following properties: \n ${JSON.stringify(data)}`);
    }
  }
};
