/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */
import { Injectable } from '@angular/core';

import { environment } from '../../environments/environment';
import { Logger } from 'app/shared/logger.service';

@Injectable()
/**
 * Google Analytics Service - captures app behaviors and sends them to Google Analytics (GA).
 * Presupposes that GA script has been loaded from a script on the host web page.
 * Associates data with a GA "property" from the environment (`gaId`).
 */
export class GaService {
  // ms to wait before acquiring window.ga after analytics library loads
  // empirically determined to allow time for e2e test setup
  static initializeDelay = 1000;

  private previousUrl: string;
  private ga: (...rest: any[]) => void;

  constructor(private logger: Logger) {
    this.initializeGa();
    this.ga('create', environment['gaId'] , 'auto');
  }

  locationChanged(url: string) {
    this.sendPage(url);
  }

  sendPage(url: string) {
    // Won't re-send if the url hasn't changed.
    if (url === this.previousUrl) { return; }
    this.previousUrl = url;
    this.ga('set', 'page', '/' + url);
    this.ga('send', 'pageview');
  }

  // These gyrations are necessary to make the service e2e testable
  // and to disable ga tracking during e2e tests.
  private initializeGa() {
    const ga = window['ga'];
    if (ga) {
      // Queue commands until GA analytics script has loaded.
      const gaQueue: any[][] = [];
      this.ga = (...rest: any[]) => { gaQueue.push(rest); };

      // Then send queued commands to either real or e2e test ga();
      // after waiting to allow possible e2e test to replace global ga function
      ga(() => setTimeout(() => {
        // this.logging.log('GA fn:', window['ga'].toString());
        this.ga = window['ga'];
        gaQueue.forEach((command) => this.ga.apply(null, command));
      }, GaService.initializeDelay));

    } else {
      // delegate `ga` calls to the logging if no ga installed
      this.ga = (...rest: any[]) => { this.logger.log('ga:', rest); };
    }
  }

}
