import { Reporter } from 'tachyon-spade-reporter';
import { SpadeData } from 'mweb/common/selectors/tracking/base';

export interface SpadeEvent {
  event: string;
  properties: SpadeData;
}

export class Tracker {
  private trackingParams: Object;

  constructor(
    private reporter: Reporter,
    appVersion: string,
    private deviceID: string,
    private sessionID: string,
    preferredLanguage?: string,
    receivedLanguage?: string,
  ) {
    this.trackingParams = {
      app_version: appVersion,
      browser: navigator.userAgent,
      device_id: this.deviceID,
      domain: window.location.hostname,
      host: this.buildHost(window.location),
      referrer_host: getReferrerHost(),
      referrer_domain: getReferrerDomain(),
      // Intentionally duplicated field.
      referrer: window.document.referrer || undefined,
      preferred_language: preferredLanguage,
      received_language: receivedLanguage,
      app_session_id: this.sessionID,
    };
  }

  get liveTrackingParams(): object {
    return {
      url: window.document.location.href,
      viewport_height: window.innerHeight,
      viewport_width: window.innerWidth,
    };
  }

  static get nonLowercasableFields(): string[] {
    return [
      'app_session_id',
      'benchmark_session_id',
      'browser',
      'device_id',
      'interaction_target_path',
    ];
  }

  trackEvent(event: SpadeEvent | undefined): void {
    if (!event) {
      return;
    }

    const properties: any = {
      ...event.properties,
      ...this.trackingParams,
      ...this.liveTrackingParams,
      device_orientation: getDeviceOrientation(),
    };

    Object.keys(properties).forEach(key => {
      const value = properties[key];
      if (
        value &&
        !Tracker.nonLowercasableFields.includes(key) &&
        value.toLowerCase
      ) {
        properties[key] = value.toLowerCase();
      }
    });

    this.reporter.reportEvent({ event: event.event, properties });
  }

  private buildHost(loc: Location): string {
    return `${loc.protocol}//${loc.hostname}`;
  }
}

export function getReferrerHost(
  referrer: string = window.document.referrer,
): string | undefined {
  try {
    return new URL(referrer).host;
  } catch (e) {
    return undefined;
  }
}

export function getReferrerDomain(
  referrer: string = window.document.referrer,
): string | undefined {
  const host = getReferrerHost(referrer);
  return host ? (host.match(/([^.]+\.[^.]+)$/) || [])[1] : undefined;
}

enum DeviceOrientation {
  Portrait = 'portrait',
  Landscape = 'landscape',
}

export function getDeviceOrientation(): DeviceOrientation {
  if (window.screen && window.screen.orientation) {
    return window.screen.orientation.type.split('-')[0] as DeviceOrientation;
  } else if (typeof window.orientation === 'number') {
    const orientation = Math.abs(window.orientation);
    if (45 < orientation && orientation < 135) {
      return DeviceOrientation.Landscape;
    } else {
      return DeviceOrientation.Portrait;
    }
  } else {
    return document.documentElement.clientWidth >
      document.documentElement.clientHeight
      ? DeviceOrientation.Landscape
      : DeviceOrientation.Portrait;
  }
}
