import {
  getSpadeDataWithLocation,
  SpadeDataWithLocation,
  PLATFORM_FOR_SPADE,
} from 'mweb/common/selectors/tracking/base';

import { Location } from 'mweb/common/reducers/app';
import { RootState } from 'mweb/common/reducers/root';
import { NetInfo } from 'src/common/actions/platform';

interface LatencySpadeDataOpts {
  state: RootState;
  epochTime: number;
}
interface LatencySpadeData extends SpadeDataWithLocation {
  benchmark_session_id: string;
  client_app: typeof PLATFORM_FOR_SPADE;
  client_time: number; // seconds since epoch as float
  destination: Location;
}
export function getLatencySpadeData({
  state,
  epochTime,
}: LatencySpadeDataOpts): LatencySpadeData {
  return {
    ...getSpadeDataWithLocation(state),
    client_time: epochTime / 1000,
    benchmark_session_id: state.device.sessionID,
    client_app: PLATFORM_FOR_SPADE,
    destination: state.app.location,
  };
}

interface LatencyBandwidthSpadeDataOpts extends LatencySpadeDataOpts {}
interface LatencyBandwidthSpadeData extends LatencySpadeData, NetInfo {}
export function getLatencyBandwidthSpadeData({
  state,
  epochTime,
}: LatencyBandwidthSpadeDataOpts): LatencyBandwidthSpadeData {
  return {
    ...getLatencySpadeData({ state, epochTime }),
    ...state.device.netInfo,
  };
}

/**
 * We've changed the meaning of this event to time how long since navigation.
 * Previously, this was pegged at time since the navigationStart event, but
 * this made tracking in-app transition timings extremely difficult. The event's
 * key is still `time_from_fetch` to avoid altering the schema, but the value's
 * meaning has been updated to be more like `time_from_page`.
 */
interface LatencyTransitionCompleteSpadeDataOpts extends LatencySpadeDataOpts {
  timeFromPage: number;
  isFirstPage: boolean;
  isDocumentHidden: boolean;
}
interface LatencyTransitionCompleteSpadeData extends LatencyBandwidthSpadeData {
  lost_visibility: boolean;
  time_from_fetch: number; // milliseconds, must be int
  is_app_launch: boolean;
}
export function getLatencyBandwidthTransitionCompleteSpadeData({
  state,
  epochTime,
  timeFromPage,
  isFirstPage: is_app_launch,
  isDocumentHidden: lost_visibility,
}: LatencyTransitionCompleteSpadeDataOpts): LatencyTransitionCompleteSpadeData {
  return {
    ...getLatencyBandwidthSpadeData({ state, epochTime }),
    time_from_fetch: Math.round(timeFromPage),
    lost_visibility,
    is_app_launch,
  };
}

interface LatencyComponentInitSpadeDataOpts extends LatencySpadeDataOpts {
  name: string;
  id: number;
  parentName: string;
  parentID: number;
}
interface LatencyComponentInitSpadeData extends LatencySpadeData {
  component: string;
  component_id: number;
  parent_component: string;
  parent_component_id: number;
}
export function getLatencyComponentInitSpadeData({
  state,
  epochTime,
  name: component,
  id: component_id,
  parentName: parent_component,
  parentID: parent_component_id,
}: LatencyComponentInitSpadeDataOpts): LatencyComponentInitSpadeData {
  return {
    ...getLatencySpadeData({ state, epochTime }),
    component,
    component_id,
    parent_component,
    parent_component_id,
  };
}

interface LatencyComponentInteractiveSpadeDataOpts
  extends LatencySpadeDataOpts {
  timeFromInit: number;
  name: string;
  id: number;
  parentName: string;
  parentID: number;
  isCritical: boolean;
}
interface LatencyComponentInteractiveSpadeData
  extends LatencyComponentInitSpadeData {
  time_from_initializing: number; // seconds, as float
  is_pre_pageload: boolean;
}
export function getLatencyComponentInteractiveSpadeData({
  state,
  epochTime,
  timeFromInit,
  name: component,
  id: component_id,
  parentName: parent_component,
  parentID: parent_component_id,
  isCritical: is_pre_pageload,
}: LatencyComponentInteractiveSpadeDataOpts): LatencyComponentInteractiveSpadeData {
  return {
    ...getLatencySpadeData({ state, epochTime }),
    time_from_initializing: timeFromInit / 1000,
    component,
    component_id,
    parent_component,
    parent_component_id,
    is_pre_pageload,
  };
}

interface LatencyCustomEventSpadeDataOpts
  extends ObjectOmit<LatencyTransitionCompleteSpadeDataOpts, 'timeFromPage'> {
  duration: number;
  group: string;
  key: string;
  label: string;
}
interface LatencyCustomEventSpadeData extends LatencySpadeData {
  duration: number; // milliseconds, must be int
  group: string;
  key: string;
  label: string;
  is_app_launch: boolean;
  lost_visibility: boolean;
}
export function getLatencyCustomEventSpadeData({
  state,
  epochTime,
  duration,
  group,
  key,
  label,
  isFirstPage: is_app_launch,
  isDocumentHidden: lost_visibility,
}: LatencyCustomEventSpadeDataOpts): LatencyCustomEventSpadeData {
  return {
    ...getLatencySpadeData({ state, epochTime }),
    duration: Math.round(duration),
    group,
    key,
    label,
    is_app_launch,
    lost_visibility,
  };
}
