import { SpadeEventData } from "../../types/SpadeEventData";
import { regex } from "../../regex";
import { InfluxFields, InfluxTags } from "../../types/influx";
import { TwilightDataPoint } from "../TwilightDataPoint";

export class NetworkRequest extends TwilightDataPoint {

  // Tags
  is_pre_pageload: boolean;

  // Fields
  dns_duration: number;
  connect_duration: number;
  response_duration: number;
  redirect_duration: number;
  request_duration: number;
  transfer_size: number;
  duration: number;
  request_url: string;
  start_time: number;
  relative_start_time: number;
  relative_complete_time: number;

  constructor(fields: SpadeEventData) {
    super('network_request', fields);

    this.is_pre_pageload = this.parseBool(fields.is_pre_pageload);

    this.dns_duration = +fields.dns_duration;
    this.connect_duration = +fields.connect_duration;
    this.redirect_duration = +fields.redirect_duration;
    this.request_duration = +fields.request_duration;
    this.response_duration = +fields.response_duration;
    this.transfer_size = +fields.transfer_size;
    this.duration = +fields.duration;

    this.request_url = this.parseURL(fields.request_url);
    this.start_time = +fields.start_time_utc_ts;

    if (fields.hasOwnProperty('relative_start_time')) {
      this.relative_start_time = +fields.relative_start_time;
      this.relative_complete_time = this.duration + this.relative_start_time;
    } else {
      this.relative_start_time = 0;
      this.relative_complete_time = 0;
    }
  }

  request_type(): string {
    switch (true) {
      case regex.IsCoreJS.test(this.request_url):
        return 'Static - Core.js';
      case regex.IsSettingsJS.test(this.request_url):
        return 'Static - Settings.js';
      case regex.IsManifestJS.test(this.request_url):
        return 'Static - Manifest.js';
      case regex.IsVendorJS.test(this.request_url):
        return 'Static - Vendor.js';
      case regex.IsCoreCSS.test(this.request_url):
        return 'Static - Core.css';
      case regex.IsWorkerJS.test(this.request_url):
        return 'Static - Worker.js';
      case regex.IsPolyfillJS.test(this.request_url):
        return 'Static - Polyfill.js';
      case regex.IsTwilightImage.test(this.request_url):
        let image_matches = regex.IsTwilightImage.exec(this.request_url);
        if (image_matches) {
          return `Static - Images - ${image_matches[1]}`;
        } else {
          return 'Static - Images';
        }
      case regex.IsPageJS.test(this.request_url):
        let page_matches = regex.IsPageJS.exec(this.request_url);
        if (page_matches) {
          return `Static - Pages.js - ${page_matches[1]}`;
        } else {
          return 'Static - Pages.js';
        }
      case regex.IsLocalesJS.test(this.request_url):
        let locale_matches = regex.IsLocalesJS.exec(this.request_url);
        if (locale_matches) {
          return `Static - Locale.js - ${locale_matches[1]}`;
        } else {
          return 'Static - Locale.js';
        }
      case regex.IsEntryJS.test(this.request_url):
        let entry_matches = regex.IsLocalesJS.exec(this.request_url);
        if (entry_matches) {
          return `Static - Entry.${entry_matches[2]} - ${entry_matches[1]}`;
        } else {
          return 'Static - Entry';
        }
      case regex.IsFavicon.test(this.request_url):
        return 'Static - Favicon';
      case regex.IsCustos.test(this.request_url):
        return 'Static - SourcePoint';
      case regex.IsGraphQL.test(this.request_url):
        return 'GraphQL';
      case regex.IsKraken.test(this.request_url):
        let kraken_matches = regex.IsKraken.exec(this.request_url);
        if (kraken_matches) {
          return `API - Kraken - ${kraken_matches[3]}`;
        } else {
          return 'API - Kraken';
        }
      case regex.IsViewerToken.test(this.request_url):
        return 'API - Viewer Token';
      case regex.IsAPIMe.test(this.request_url):
        return 'API - Me'
      case regex.IsProductionSage.test(this.request_url):
        return 'Sage';
      case regex.IsJtvnw.test(this.request_url):
        let jtvnw_matches = regex.IsJtvnw.exec(this.request_url);
        if (jtvnw_matches) {
          return `JTVNW - ${jtvnw_matches[2]}`;
        } else {
          return 'JTVNW - Other';
        }
      case regex.IsPlayerJS.test(this.request_url):
        return 'Player - player.js';
      case regex.IsPlayerCSS.test(this.request_url):
        return 'Player - player.css';
      case regex.IsPlayerOther.test(this.request_url):
        return 'Player - Other'
      case regex.IsClientReporter.test(this.request_url):
        return 'Client Reporter';
      case regex.IsClipsMediaAssets.test(this.request_url):
        return 'Clips - Media Assets';
      case regex.IsVodStoryboards.test(this.request_url):
        return 'VOD Storyboards';
      case regex.IsSentinel.test(this.request_url):
        return 'Sentinel';
      case regex.IsPubSub.test(this.request_url):
        return 'PubSub - Websocket';
      case regex.IsPubster.test(this.request_url):
        return 'PubSub - Pubster';
      case regex.IsIRC.test(this.request_url):
        return 'Chat - Websocket'
      case regex.IsClips.test(this.request_url):
        return 'Clips'
      default:
        return 'Uncategorized';
    }
  }

  cdn(): string {
    switch (true) {
      case regex.IsAkamai.test(this.request_url):
        return 'Akamai';
      case regex.IsCloudFront.test(this.request_url):
        return 'CloudFront';
      case regex.IsCloudFlare.test(this.request_url):
        return 'CloudFlare';
      case regex.IsFastly.test(this.request_url):
        return 'Fastly';
      case regex.IsControl.test(this.request_url):
        return 'Control'
      default:
        return ''
    }
  }

  getFields(): InfluxFields {
    return {
      dns_duration: this.dns_duration,
      connect_duration: this.connect_duration,
      redirect_duration: this.redirect_duration,
      request_duration: this.request_duration,
      response_duration: this.response_duration,
      transfer_size: this.transfer_size,
      duration: this.duration,
      request_url: this.request_url,
      start_time: this.start_time,
      relative_start_time: this.relative_start_time,
      relative_complete_time: this.relative_complete_time,
      ...super.getFields()
    }
  }

  getTags(): InfluxTags {
    return {
      is_pre_pageload: String(this.is_pre_pageload),
      cdn: this.cdn(),
      request_type: this.request_type(),
      browser_cache_hit: this.transfer_size == 0 ? 'true' : 'false',
      duration_outlier: String(this.duration < 0 || this.duration > 120000),
      ...super.getTags()
    }
  }
}
