// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {Draft} from 'immer';

import {assertExists, assertTrue} from '../base/logging';
import {duration, time} from '../base/time';
import {RecordConfig} from '../controller/record_config_types';
import {
  GenericSliceDetailsTabConfig,
  GenericSliceDetailsTabConfigBase,
} from '../frontend/generic_slice_details_tab';
import {
  Aggregation,
  AggregationFunction,
  TableColumn,
  tableColumnEquals,
  toggleEnabled,
} from '../frontend/pivot_table_types';
import {PrimaryTrackSortKey} from '../public/index';

import {randomColor} from '../core/colorizer';
import {
  computeIntervals,
  DropDirection,
  performReordering,
} from './dragndrop_logic';
import {createEmptyState} from './empty_state';
import {defaultViewingOption} from './flamegraph_util';
import {
  MetatraceTrackId,
  traceEventBegin,
  traceEventEnd,
  TraceEventScope,
} from './metatracing';
import {
  AdbRecordingTarget,
  Area,
  CallsiteInfo,
  EngineMode,
  FlamegraphStateViewingOption,
  LoadedConfig,
  NewEngineMode,
  OmniboxMode,
  OmniboxState,
  Pagination,
  PendingDeeplinkState,
  PivotTableResult,
  ProfileType,
  RecordingTarget,
  SCROLLING_TRACK_GROUP,
  SortDirection,
  State,
  Status,
  ThreadTrackSortKey,
  TraceTime,
  TrackSortKey,
  UtidToTrackSortKey,
  VisibleState,
} from './state';

type StateDraft = Draft<State>;

export interface AddTrackArgs {
  key?: string;
  uri: string;
  name: string;
  labels?: string[];
  trackSortKey: TrackSortKey;
  trackGroup?: string;
  params?: unknown;
  closeable?: boolean;
}

export interface PostedTrace {
  buffer: ArrayBuffer;
  title: string;
  fileName?: string;
  url?: string;
  uuid?: string;
  localOnly?: boolean;
  keepApiOpen?: boolean;
}

export interface PostedScrollToRange {
  timeStart: number;
  timeEnd: number;
  viewPercentage?: number;
}

function clearTraceState(state: StateDraft) {
  const nextId = state.nextId;
  const recordConfig = state.recordConfig;
  const recordingTarget = state.recordingTarget;
  const fetchChromeCategories = state.fetchChromeCategories;
  const extensionInstalled = state.extensionInstalled;
  const availableAdbDevices = state.availableAdbDevices;
  const chromeCategories = state.chromeCategories;
  const newEngineMode = state.newEngineMode;

  Object.assign(state, createEmptyState());
  state.nextId = nextId;
  state.recordConfig = recordConfig;
  state.recordingTarget = recordingTarget;
  state.fetchChromeCategories = fetchChromeCategories;
  state.extensionInstalled = extensionInstalled;
  state.availableAdbDevices = availableAdbDevices;
  state.chromeCategories = chromeCategories;
  state.newEngineMode = newEngineMode;
}

function generateNextId(draft: StateDraft): string {
  const nextId = String(Number(draft.nextId) + 1);
  draft.nextId = nextId;
  return nextId;
}

// A helper to clean the state for a given removeable track.
// This is not exported as action to make it clear that not all
// tracks are removeable.
function removeTrack(state: StateDraft, trackKey: string) {
  const track = state.tracks[trackKey];
  if (track === undefined) {
    return;
  }
  delete state.tracks[trackKey];

  const removeTrackId = (arr: string[]) => {
    const index = arr.indexOf(trackKey);
    if (index !== -1) arr.splice(index, 1);
  };

  if (track.trackGroup === SCROLLING_TRACK_GROUP) {
    removeTrackId(state.scrollingTracks);
  } else if (track.trackGroup !== undefined) {
    const trackGroup = state.trackGroups[track.trackGroup];
    if (trackGroup !== undefined) {
      removeTrackId(trackGroup.tracks);
    }
  }
  state.pinnedTracks = state.pinnedTracks.filter((key) => key !== trackKey);
}

let statusTraceEvent: TraceEventScope | undefined;

export const StateActions = {
  openTraceFromFile(state: StateDraft, args: {file: File}): void {
    clearTraceState(state);
    const id = generateNextId(state);
    state.engine = {
      id,
      ready: false,
      source: {type: 'FILE', file: args.file},
    };
  },

  openTraceFromBuffer(state: StateDraft, args: PostedTrace): void {
    clearTraceState(state);
    const id = generateNextId(state);
    state.engine = {
      id,
      ready: false,
      source: {type: 'ARRAY_BUFFER', ...args},
    };
  },

  openTraceFromUrl(state: StateDraft, args: {url: string}): void {
    clearTraceState(state);
    const id = generateNextId(state);
    state.engine = {
      id,
      ready: false,
      source: {type: 'URL', url: args.url},
    };
  },

  openTraceFromHttpRpc(state: StateDraft, _args: {}): void {
    clearTraceState(state);
    const id = generateNextId(state);
    state.engine = {
      id,
      ready: false,
      source: {type: 'HTTP_RPC'},
    };
  },

  setTraceUuid(state: StateDraft, args: {traceUuid: string}) {
    state.traceUuid = args.traceUuid;
  },

  addTracks(state: StateDraft, args: {tracks: AddTrackArgs[]}) {
    args.tracks.forEach((track) => {
      const trackKey =
        track.key === undefined ? generateNextId(state) : track.key;
      const name = track.name;
      state.tracks[trackKey] = {
        key: trackKey,
        name,
        trackSortKey: track.trackSortKey,
        trackGroup: track.trackGroup,
        labels: track.labels,
        uri: track.uri,
        params: track.params,
        closeable: track.closeable,
      };
      if (track.trackGroup === SCROLLING_TRACK_GROUP) {
        state.scrollingTracks.push(trackKey);
      } else if (track.trackGroup !== undefined) {
        const group = state.trackGroups[track.trackGroup];
        if (group !== undefined) {
          group.tracks.push(trackKey);
        }
      }
    });
  },

  // Note: While this action has traditionally been omitted, with more and more
  // dynamic tracks being added and existing ones being moved to plugins, it
  // makes sense to have a generic "removeTracks" action which is un-opinionated
  // about what type of tracks we are removing.
  // E.g. Once debug tracks have been moved to a plugin, it makes no sense to
  // keep the "removeDebugTrack()" action, as the core should have no concept of
  // what debug tracks are.
  removeTracks(state: StateDraft, args: {trackKeys: string[]}) {
    for (const trackKey of args.trackKeys) {
      removeTrack(state, trackKey);
    }
  },

  setUtidToTrackSortKey(
    state: StateDraft,
    args: {threadOrderingMetadata: UtidToTrackSortKey},
  ) {
    state.utidToThreadSortKey = args.threadOrderingMetadata;
  },

  addTrack(state: StateDraft, args: AddTrackArgs): void {
    this.addTracks(state, {tracks: [args]});
  },

  addTrackGroup(
    state: StateDraft,
    // Define ID in action so a track group can be referred to without running
    // the reducer.
    args: {
      name: string;
      id: string;
      summaryTrackKey?: string;
      collapsed: boolean;
      fixedOrdering?: boolean;
    },
  ): void {
    state.trackGroups[args.id] = {
      name: args.name,
      id: args.id,
      collapsed: args.collapsed,
      tracks: [],
      summaryTrack: args.summaryTrackKey,
      fixedOrdering: args.fixedOrdering,
    };
  },

  maybeExpandOnlyTrackGroup(state: StateDraft, _: {}): void {
    const trackGroups = Object.values(state.trackGroups);
    if (trackGroups.length === 1) {
      trackGroups[0].collapsed = false;
    }
  },

  sortThreadTracks(state: StateDraft, _: {}) {
    const getFullKey = (a: string) => {
      const track = state.tracks[a];
      const threadTrackSortKey = track.trackSortKey as ThreadTrackSortKey;
      if (threadTrackSortKey.utid === undefined) {
        const sortKey = track.trackSortKey as PrimaryTrackSortKey;
        return [sortKey, 0, 0, 0];
      }
      const threadSortKey = state.utidToThreadSortKey[threadTrackSortKey.utid];
      return [
        /* eslint-disable @typescript-eslint/strict-boolean-expressions */
        threadSortKey
          ? threadSortKey.sortKey
          : PrimaryTrackSortKey.ORDINARY_THREAD,
        threadSortKey && threadSortKey.tid !== undefined
          ? threadSortKey.tid
          : Number.MAX_VALUE,
        /* eslint-enable */
        threadTrackSortKey.utid,
        threadTrackSortKey.priority,
      ];
    };

    // Use a numeric collator so threads are sorted as T1, T2, ..., T10, T11,
    // rather than T1, T10, T11, ..., T2, T20, T21 .
    const coll = new Intl.Collator([], {sensitivity: 'base', numeric: true});
    for (const group of Object.values(state.trackGroups)) {
      if (group.fixedOrdering) continue;

      group.tracks.sort((a: string, b: string) => {
        const aRank = getFullKey(a);
        const bRank = getFullKey(b);
        for (let i = 0; i < aRank.length; i++) {
          if (aRank[i] !== bRank[i]) return aRank[i] - bRank[i];
        }

        const aName = state.tracks[a].name.toLocaleLowerCase();
        const bName = state.tracks[b].name.toLocaleLowerCase();
        return coll.compare(aName, bName);
      });
    }
  },

  updateAggregateSorting(
    state: StateDraft,
    args: {id: string; column: string},
  ) {
    let prefs = state.aggregatePreferences[args.id];
    // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
    if (!prefs) {
      prefs = {id: args.id};
      state.aggregatePreferences[args.id] = prefs;
    }

    if (!prefs.sorting || prefs.sorting.column !== args.column) {
      // No sorting set for current column.
      state.aggregatePreferences[args.id].sorting = {
        column: args.column,
        direction: 'DESC',
      };
    } else if (prefs.sorting.direction === 'DESC') {
      // Toggle the direction if the column is currently sorted.
      state.aggregatePreferences[args.id].sorting = {
        column: args.column,
        direction: 'ASC',
      };
    } else {
      // If direction is currently 'ASC' toggle to no sorting.
      state.aggregatePreferences[args.id].sorting = undefined;
    }
  },

  moveTrack(
    state: StateDraft,
    args: {srcId: string; op: 'before' | 'after'; dstId: string},
  ): void {
    const moveWithinTrackList = (trackList: string[]) => {
      const newList: string[] = [];
      for (let i = 0; i < trackList.length; i++) {
        const curTrackId = trackList[i];
        if (curTrackId === args.dstId && args.op === 'before') {
          newList.push(args.srcId);
        }
        if (curTrackId !== args.srcId) {
          newList.push(curTrackId);
        }
        if (curTrackId === args.dstId && args.op === 'after') {
          newList.push(args.srcId);
        }
      }
      trackList.splice(0);
      newList.forEach((x) => {
        trackList.push(x);
      });
    };

    moveWithinTrackList(state.pinnedTracks);
    moveWithinTrackList(state.scrollingTracks);
  },

  toggleTrackPinned(state: StateDraft, args: {trackKey: string}): void {
    const key = args.trackKey;
    const isPinned = state.pinnedTracks.includes(key);
    const trackGroup = assertExists(state.tracks[key]).trackGroup;

    if (isPinned) {
      state.pinnedTracks.splice(state.pinnedTracks.indexOf(key), 1);
      if (trackGroup === SCROLLING_TRACK_GROUP) {
        state.scrollingTracks.unshift(key);
      }
    } else {
      if (trackGroup === SCROLLING_TRACK_GROUP) {
        state.scrollingTracks.splice(state.scrollingTracks.indexOf(key), 1);
      }
      state.pinnedTracks.push(key);
    }
  },

  toggleTrackGroupCollapsed(
    state: StateDraft,
    args: {trackGroupId: string},
  ): void {
    const id = args.trackGroupId;
    const trackGroup = assertExists(state.trackGroups[id]);
    trackGroup.collapsed = !trackGroup.collapsed;
  },

  requestTrackReload(state: StateDraft, _: {}) {
    // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
    if (state.lastTrackReloadRequest) {
      state.lastTrackReloadRequest++;
    } else {
      state.lastTrackReloadRequest = 1;
    }
  },

  maybeSetPendingDeeplink(state: StateDraft, args: PendingDeeplinkState) {
    state.pendingDeeplink = args;
  },

  clearPendingDeeplink(state: StateDraft, _: {}) {
    state.pendingDeeplink = undefined;
  },

  // TODO(hjd): engine.ready should be a published thing. If it's part
  // of the state it interacts badly with permalinks.
  setEngineReady(
    state: StateDraft,
    args: {engineId: string; ready: boolean; mode: EngineMode},
  ): void {
    const engine = state.engine;
    if (engine === undefined || engine.id !== args.engineId) {
      return;
    }
    engine.ready = args.ready;
    engine.mode = args.mode;
  },

  setNewEngineMode(state: StateDraft, args: {mode: NewEngineMode}): void {
    state.newEngineMode = args.mode;
  },

  // Marks all engines matching the given |mode| as failed.
  setEngineFailed(
    state: StateDraft,
    args: {mode: EngineMode; failure: string},
  ): void {
    if (state.engine !== undefined && state.engine.mode === args.mode) {
      state.engine.failed = args.failure;
    }
  },

  createPermalink(state: StateDraft, args: {isRecordingConfig: boolean}): void {
    state.permalink = {
      requestId: generateNextId(state),
      hash: undefined,
      isRecordingConfig: args.isRecordingConfig,
    };
  },

  setPermalink(
    state: StateDraft,
    args: {requestId: string; hash: string},
  ): void {
    // Drop any links for old requests.
    if (state.permalink.requestId !== args.requestId) return;
    state.permalink = args;
  },

  loadPermalink(state: StateDraft, args: {hash: string}): void {
    state.permalink = {requestId: generateNextId(state), hash: args.hash};
  },

  clearPermalink(state: StateDraft, _: {}): void {
    state.permalink = {};
  },

  setTraceTime(state: StateDraft, args: TraceTime): void {
    state.traceTime = args;
  },

  updateStatus(state: StateDraft, args: Status): void {
    if (statusTraceEvent) {
      traceEventEnd(statusTraceEvent);
    }
    statusTraceEvent = traceEventBegin(args.msg, {
      track: MetatraceTrackId.kOmniboxStatus,
    });
    state.status = args;
  },

  // TODO(hjd): Remove setState - it causes problems due to reuse of ids.
  setState(state: StateDraft, args: {newState: State}): void {
    for (const key of Object.keys(state)) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      delete (state as any)[key];
    }
    for (const key of Object.keys(args.newState)) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (state as any)[key] = (args.newState as any)[key];
    }

    // If we're loading from a permalink then none of the engines can
    // possibly be ready:
    if (state.engine !== undefined) {
      state.engine.ready = false;
    }
  },

  setRecordConfig(
    state: StateDraft,
    args: {config: RecordConfig; configType?: LoadedConfig},
  ): void {
    state.recordConfig = args.config;
    state.lastLoadedConfig = args.configType || {type: 'NONE'};
  },

  selectNote(state: StateDraft, args: {id: string}): void {
    if (args.id) {
      state.selection = {
        kind: 'legacy',
        legacySelection: {
          kind: 'NOTE',
          id: args.id,
        },
      };
    }
  },

  addAutomaticNote(
    state: StateDraft,
    args: {timestamp: time; color: string; text: string},
  ): void {
    const id = generateNextId(state);
    state.notes[id] = {
      noteType: 'DEFAULT',
      id,
      timestamp: args.timestamp,
      color: args.color,
      text: args.text,
    };
  },

  addNote(state: StateDraft, args: {timestamp: time; color: string}): void {
    const id = generateNextId(state);
    state.notes[id] = {
      noteType: 'DEFAULT',
      id,
      timestamp: args.timestamp,
      color: args.color,
      text: '',
    };
    this.selectNote(state, {id});
  },

  markCurrentArea(
    state: StateDraft,
    args: {color: string; persistent: boolean},
  ): void {
    if (state.selection.kind !== 'legacy') {
      return;
    }
    if (state.selection.legacySelection.kind !== 'AREA') {
      return;
    }
    const legacySelection = state.selection.legacySelection;
    const id = args.persistent ? generateNextId(state) : '0';
    const color = args.persistent ? args.color : '#344596';
    state.notes[id] = {
      noteType: 'AREA',
      id,
      areaId: legacySelection.areaId,
      color,
      text: '',
    };
    legacySelection.noteId = id;
  },

  toggleMarkCurrentArea(state: StateDraft, args: {persistent: boolean}) {
    const selection = state.selection;
    if (
      selection.kind === 'legacy' &&
      selection.legacySelection.kind === 'AREA' &&
      selection.legacySelection.noteId !== undefined
    ) {
      this.removeNote(state, {id: selection.legacySelection.noteId});
    } else {
      const color = randomColor();
      this.markCurrentArea(state, {color, persistent: args.persistent});
    }
  },

  markArea(state: StateDraft, args: {area: Area; persistent: boolean}): void {
    const {start, end, tracks} = args.area;
    assertTrue(start <= end);
    const areaId = generateNextId(state);
    state.areas[areaId] = {id: areaId, start, end, tracks};
    const noteId = args.persistent ? generateNextId(state) : '0';
    const color = args.persistent ? randomColor() : '#344596';
    state.notes[noteId] = {
      noteType: 'AREA',
      id: noteId,
      areaId,
      color,
      text: '',
    };
  },

  changeNoteColor(
    state: StateDraft,
    args: {id: string; newColor: string},
  ): void {
    const note = state.notes[args.id];
    if (note === undefined) return;
    note.color = args.newColor;
  },

  changeNoteText(state: StateDraft, args: {id: string; newText: string}): void {
    const note = state.notes[args.id];
    if (note === undefined) return;
    note.text = args.newText;
  },

  removeNote(state: StateDraft, args: {id: string}): void {
    if (state.notes[args.id] === undefined) return;
    delete state.notes[args.id];
    // For regular notes, we clear the current selection but for an area note
    // we only want to clear the note/marking and leave the area selected.
    if (state.selection.kind !== 'legacy') return;
    if (
      state.selection.legacySelection.kind === 'NOTE' &&
      state.selection.legacySelection.id === args.id
    ) {
      state.selection = {
        kind: 'empty',
      };
    } else if (
      state.selection.legacySelection.kind === 'AREA' &&
      state.selection.legacySelection.noteId === args.id
    ) {
      state.selection.legacySelection.noteId = undefined;
    }
  },

  selectCounter(
    state: StateDraft,
    args: {leftTs: time; rightTs: time; id: number; trackKey: string},
  ): void {
    state.selection = {
      kind: 'legacy',
      legacySelection: {
        kind: 'COUNTER',
        leftTs: args.leftTs,
        rightTs: args.rightTs,
        id: args.id,
        trackKey: args.trackKey,
      },
    };
  },

  selectHeapProfile(
    state: StateDraft,
    args: {id: number; upid: number; ts: time; type: ProfileType},
  ): void {
    state.selection = {
      kind: 'legacy',
      legacySelection: {
        kind: 'HEAP_PROFILE',
        id: args.id,
        upid: args.upid,
        ts: args.ts,
        type: args.type,
      },
    };
    this.openFlamegraph(state, {
      type: args.type,
      start: state.traceTime.start as time, // TODO(stevegolton): Avoid type assertion here.
      end: args.ts,
      upids: [args.upid],
      viewingOption: defaultViewingOption(args.type),
    });
  },

  selectPerfSamples(
    state: StateDraft,
    args: {
      id: number;
      upid: number;
      leftTs: time;
      rightTs: time;
      type: ProfileType;
    },
  ): void {
    state.selection = {
      kind: 'legacy',
      legacySelection: {
        kind: 'PERF_SAMPLES',
        id: args.id,
        upid: args.upid,
        leftTs: args.leftTs,
        rightTs: args.rightTs,
        type: args.type,
      },
    };
    this.openFlamegraph(state, {
      type: args.type,
      start: args.leftTs,
      end: args.rightTs,
      upids: [args.upid],
      viewingOption: defaultViewingOption(args.type),
    });
  },

  openFlamegraph(
    state: StateDraft,
    args: {
      upids: number[];
      start: time;
      end: time;
      type: ProfileType;
      viewingOption: FlamegraphStateViewingOption;
    },
  ): void {
    state.currentFlamegraphState = {
      kind: 'FLAMEGRAPH_STATE',
      upids: args.upids,
      start: args.start,
      end: args.end,
      type: args.type,
      viewingOption: args.viewingOption,
      focusRegex: '',
      expandedCallsiteByViewingOption: {},
    };
  },

  selectCpuProfileSample(
    state: StateDraft,
    args: {id: number; utid: number; ts: time},
  ): void {
    state.selection = {
      kind: 'legacy',
      legacySelection: {
        kind: 'CPU_PROFILE_SAMPLE',
        id: args.id,
        utid: args.utid,
        ts: args.ts,
      },
    };
  },

  expandFlamegraphState(
    state: StateDraft,
    args: {
      expandedCallsite?: CallsiteInfo;
      viewingOption: FlamegraphStateViewingOption;
    },
  ): void {
    if (state.currentFlamegraphState === null) return;
    state.currentFlamegraphState.expandedCallsiteByViewingOption[
      args.viewingOption
    ] = args.expandedCallsite;
  },

  changeViewFlamegraphState(
    state: StateDraft,
    args: {viewingOption: FlamegraphStateViewingOption},
  ): void {
    if (state.currentFlamegraphState === null) return;
    state.currentFlamegraphState.viewingOption = args.viewingOption;
  },

  changeFocusFlamegraphState(
    state: StateDraft,
    args: {focusRegex: string},
  ): void {
    if (state.currentFlamegraphState === null) return;
    state.currentFlamegraphState.focusRegex = args.focusRegex;
  },

  selectChromeSlice(
    state: StateDraft,
    args: {id: number; trackKey: string; table?: string; scroll?: boolean},
  ): void {
    state.selection = {
      kind: 'legacy',
      legacySelection: {
        kind: 'CHROME_SLICE',
        id: args.id,
        trackKey: args.trackKey,
        table: args.table,
      },
    };
    state.pendingScrollId = args.scroll ? args.id : undefined;
  },

  selectGenericSlice(
    state: StateDraft,
    args: {
      id: number;
      sqlTableName: string;
      start: time;
      duration: duration;
      trackKey: string;
      detailsPanelConfig: {
        kind: string;
        config: GenericSliceDetailsTabConfigBase;
      };
    },
  ): void {
    const detailsPanelConfig: GenericSliceDetailsTabConfig = {
      id: args.id,
      ...args.detailsPanelConfig.config,
    };

    state.selection = {
      kind: 'legacy',
      legacySelection: {
        kind: 'GENERIC_SLICE',
        id: args.id,
        sqlTableName: args.sqlTableName,
        start: args.start,
        duration: args.duration,
        trackKey: args.trackKey,
        detailsPanelConfig: {
          kind: args.detailsPanelConfig.kind,
          config: detailsPanelConfig,
        },
      },
    };
  },

  setPendingScrollId(state: StateDraft, args: {pendingScrollId: number}): void {
    state.pendingScrollId = args.pendingScrollId;
  },

  clearPendingScrollId(state: StateDraft, _: {}): void {
    state.pendingScrollId = undefined;
  },

  selectThreadState(
    state: StateDraft,
    args: {id: number; trackKey: string},
  ): void {
    state.selection = {
      kind: 'legacy',
      legacySelection: {
        kind: 'THREAD_STATE',
        id: args.id,
        trackKey: args.trackKey,
      },
    };
  },

  updateLogsPagination(state: StateDraft, args: Pagination): void {
    state.logsPagination = args;
  },

  startRecording(state: StateDraft, _: {}): void {
    state.recordingInProgress = true;
    state.lastRecordingError = undefined;
    state.recordingCancelled = false;
  },

  stopRecording(state: StateDraft, _: {}): void {
    state.recordingInProgress = false;
  },

  cancelRecording(state: StateDraft, _: {}): void {
    state.recordingInProgress = false;
    state.recordingCancelled = true;
  },

  setExtensionAvailable(state: StateDraft, args: {available: boolean}): void {
    state.extensionInstalled = args.available;
  },

  setRecordingTarget(state: StateDraft, args: {target: RecordingTarget}): void {
    state.recordingTarget = args.target;
  },

  setFetchChromeCategories(state: StateDraft, args: {fetch: boolean}): void {
    state.fetchChromeCategories = args.fetch;
  },

  setAvailableAdbDevices(
    state: StateDraft,
    args: {devices: AdbRecordingTarget[]},
  ): void {
    state.availableAdbDevices = args.devices;
  },

  setOmnibox(state: StateDraft, args: OmniboxState): void {
    state.omniboxState = args;
  },

  setOmniboxMode(state: StateDraft, args: {mode: OmniboxMode}): void {
    state.omniboxState.mode = args.mode;
  },

  selectArea(state: StateDraft, args: {area: Area}): void {
    const {start, end, tracks} = args.area;
    assertTrue(start <= end);
    const areaId = generateNextId(state);
    state.areas[areaId] = {id: areaId, start, end, tracks};
    state.selection = {
      kind: 'legacy',
      legacySelection: {kind: 'AREA', areaId},
    };
  },

  editArea(state: StateDraft, args: {area: Area; areaId: string}): void {
    const {start, end, tracks} = args.area;
    assertTrue(start <= end);
    state.areas[args.areaId] = {id: args.areaId, start, end, tracks};
  },

  reSelectArea(
    state: StateDraft,
    args: {areaId: string; noteId: string},
  ): void {
    state.selection = {
      kind: 'legacy',
      legacySelection: {
        kind: 'AREA',
        areaId: args.areaId,
        noteId: args.noteId,
      },
    };
  },

  toggleTrackSelection(
    state: StateDraft,
    args: {id: string; isTrackGroup: boolean},
  ) {
    const selection = state.selection;
    if (
      selection.kind !== 'legacy' ||
      selection.legacySelection.kind !== 'AREA'
    ) {
      return;
    }
    const areaId = selection.legacySelection.areaId;
    const index = state.areas[areaId].tracks.indexOf(args.id);
    if (index > -1) {
      state.areas[areaId].tracks.splice(index, 1);
      if (args.isTrackGroup) {
        // Also remove all child tracks.
        for (const childTrack of state.trackGroups[args.id].tracks) {
          const childIndex = state.areas[areaId].tracks.indexOf(childTrack);
          if (childIndex > -1) {
            state.areas[areaId].tracks.splice(childIndex, 1);
          }
        }
      }
    } else {
      state.areas[areaId].tracks.push(args.id);
      if (args.isTrackGroup) {
        // Also add all child tracks.
        for (const childTrack of state.trackGroups[args.id].tracks) {
          if (!state.areas[areaId].tracks.includes(childTrack)) {
            state.areas[areaId].tracks.push(childTrack);
          }
        }
      }
    }
    // It's super unexpected that |toggleTrackSelection| does not cause
    // selection to be updated and this leads to bugs for people who do:
    // if (oldSelection !== state.selection) etc.
    // To solve this re-create the selection object here:
    state.selection = Object.assign({}, state.selection);
  },

  setVisibleTraceTime(state: StateDraft, args: VisibleState): void {
    state.frontendLocalState.visibleState = {...args};
  },

  setChromeCategories(state: StateDraft, args: {categories: string[]}): void {
    state.chromeCategories = args.categories;
  },

  setLastRecordingError(state: StateDraft, args: {error?: string}): void {
    state.lastRecordingError = args.error;
    state.recordingStatus = undefined;
  },

  setRecordingStatus(state: StateDraft, args: {status?: string}): void {
    state.recordingStatus = args.status;
    state.lastRecordingError = undefined;
  },

  togglePerfDebug(state: StateDraft, _: {}): void {
    state.perfDebug = !state.perfDebug;
  },

  setSidebar(state: StateDraft, args: {visible: boolean}): void {
    state.sidebarVisible = args.visible;
  },

  setHoveredUtidAndPid(state: StateDraft, args: {utid: number; pid: number}) {
    state.hoveredPid = args.pid;
    state.hoveredUtid = args.utid;
  },

  setHighlightedSliceId(state: StateDraft, args: {sliceId: number}) {
    state.highlightedSliceId = args.sliceId;
  },

  setHighlightedFlowLeftId(state: StateDraft, args: {flowId: number}) {
    state.focusedFlowIdLeft = args.flowId;
  },

  setHighlightedFlowRightId(state: StateDraft, args: {flowId: number}) {
    state.focusedFlowIdRight = args.flowId;
  },

  setSearchIndex(state: StateDraft, args: {index: number}) {
    state.searchIndex = args.index;
  },

  setHoverCursorTimestamp(state: StateDraft, args: {ts: time}) {
    state.hoverCursorTimestamp = args.ts;
  },

  setHoveredNoteTimestamp(state: StateDraft, args: {ts: time}) {
    state.hoveredNoteTimestamp = args.ts;
  },

  // Add a tab with a given URI to the tab bar and show it.
  // If the tab is already present in the tab bar, just show it.
  showTab(state: StateDraft, args: {uri: string}) {
    // Add tab, unless we're talking about the special current_selection tab
    if (args.uri !== 'current_selection') {
      // Add tab to tab list if not already
      if (!state.tabs.openTabs.some((uri) => uri === args.uri)) {
        state.tabs.openTabs.push(args.uri);
      }
    }
    state.tabs.currentTab = args.uri;
  },

  // Hide a tab in the tab bar pick a new tab to show.
  // Note: Attempting to hide the "current_selection" tab doesn't work. This tab
  // is special and cannot be removed.
  hideTab(state: StateDraft, args: {uri: string}) {
    const tabs = state.tabs;
    // If the removed tab is the "current" tab, we must find a new tab to focus
    if (args.uri === tabs.currentTab) {
      // Remember the index of the current tab
      const currentTabIdx = tabs.openTabs.findIndex((uri) => uri === args.uri);

      // Remove the tab
      tabs.openTabs = tabs.openTabs.filter((uri) => uri !== args.uri);

      if (currentTabIdx !== -1) {
        if (tabs.openTabs.length === 0) {
          // No more tabs, use current selection
          tabs.currentTab = 'current_selection';
        } else if (currentTabIdx < tabs.openTabs.length - 1) {
          // Pick the tab to the right
          tabs.currentTab = tabs.openTabs[currentTabIdx];
        } else {
          // Pick the last tab
          const lastTab = tabs.openTabs[tabs.openTabs.length - 1];
          tabs.currentTab = lastTab;
        }
      }
    } else {
      // Otherwise just remove the tab
      tabs.openTabs = tabs.openTabs.filter((uri) => uri !== args.uri);
    }
  },

  clearAllPinnedTracks(state: StateDraft, _: {}) {
    const pinnedTracks = state.pinnedTracks.slice();
    for (let index = pinnedTracks.length - 1; index >= 0; index--) {
      const trackKey = pinnedTracks[index];
      this.toggleTrackPinned(state, {trackKey});
    }
  },

  togglePivotTable(state: StateDraft, args: {areaId: string | null}) {
    state.nonSerializableState.pivotTable.selectionArea =
      args.areaId === null
        ? undefined
        : {areaId: args.areaId, tracks: state.areas[args.areaId].tracks};
    if (
      args.areaId !==
      state.nonSerializableState.pivotTable.selectionArea?.areaId
    ) {
      state.nonSerializableState.pivotTable.queryResult = null;
    }
  },

  setPivotStateQueryResult(
    state: StateDraft,
    args: {queryResult: PivotTableResult | null},
  ) {
    state.nonSerializableState.pivotTable.queryResult = args.queryResult;
  },

  setPivotTableConstrainToArea(state: StateDraft, args: {constrain: boolean}) {
    state.nonSerializableState.pivotTable.constrainToArea = args.constrain;
  },

  dismissFlamegraphModal(state: StateDraft, _: {}) {
    state.flamegraphModalDismissed = true;
  },

  addPivotTableAggregation(
    state: StateDraft,
    args: {aggregation: Aggregation; after: number},
  ) {
    state.nonSerializableState.pivotTable.selectedAggregations.splice(
      args.after,
      0,
      args.aggregation,
    );
  },

  removePivotTableAggregation(state: StateDraft, args: {index: number}) {
    state.nonSerializableState.pivotTable.selectedAggregations.splice(
      args.index,
      1,
    );
  },

  setPivotTableQueryRequested(
    state: StateDraft,
    args: {queryRequested: boolean},
  ) {
    state.nonSerializableState.pivotTable.queryRequested = args.queryRequested;
  },

  setPivotTablePivotSelected(
    state: StateDraft,
    args: {column: TableColumn; selected: boolean},
  ) {
    toggleEnabled(
      tableColumnEquals,
      state.nonSerializableState.pivotTable.selectedPivots,
      args.column,
      args.selected,
    );
  },

  setPivotTableAggregationFunction(
    state: StateDraft,
    args: {index: number; function: AggregationFunction},
  ) {
    state.nonSerializableState.pivotTable.selectedAggregations[
      args.index
    ].aggregationFunction = args.function;
  },

  setPivotTableSortColumn(
    state: StateDraft,
    args: {aggregationIndex: number; order: SortDirection},
  ) {
    state.nonSerializableState.pivotTable.selectedAggregations =
      state.nonSerializableState.pivotTable.selectedAggregations.map(
        (agg, index) => ({
          column: agg.column,
          aggregationFunction: agg.aggregationFunction,
          sortDirection:
            index === args.aggregationIndex ? args.order : undefined,
        }),
      );
  },

  setPivotTableArgumentNames(
    state: StateDraft,
    args: {argumentNames: string[]},
  ) {
    state.nonSerializableState.pivotTable.argumentNames = args.argumentNames;
  },

  changePivotTablePivotOrder(
    state: StateDraft,
    args: {from: number; to: number; direction: DropDirection},
  ) {
    const pivots = state.nonSerializableState.pivotTable.selectedPivots;
    state.nonSerializableState.pivotTable.selectedPivots = performReordering(
      computeIntervals(pivots.length, args.from, args.to, args.direction),
      pivots,
    );
  },

  changePivotTableAggregationOrder(
    state: StateDraft,
    args: {from: number; to: number; direction: DropDirection},
  ) {
    const aggregations =
      state.nonSerializableState.pivotTable.selectedAggregations;
    state.nonSerializableState.pivotTable.selectedAggregations =
      performReordering(
        computeIntervals(
          aggregations.length,
          args.from,
          args.to,
          args.direction,
        ),
        aggregations,
      );
  },

  setMinimumLogLevel(state: StateDraft, args: {minimumLevel: number}) {
    state.logFilteringCriteria.minimumLevel = args.minimumLevel;
  },

  addLogTag(state: StateDraft, args: {tag: string}) {
    if (!state.logFilteringCriteria.tags.includes(args.tag)) {
      state.logFilteringCriteria.tags.push(args.tag);
    }
  },

  removeLogTag(state: StateDraft, args: {tag: string}) {
    state.logFilteringCriteria.tags = state.logFilteringCriteria.tags.filter(
      (t) => t !== args.tag,
    );
  },

  updateLogFilterText(state: StateDraft, args: {textEntry: string}) {
    state.logFilteringCriteria.textEntry = args.textEntry;
  },

  toggleCollapseByTextEntry(state: StateDraft, _: {}) {
    state.logFilteringCriteria.hideNonMatching =
      !state.logFilteringCriteria.hideNonMatching;
  },
};

// When we are on the frontend side, we don't really want to execute the
// actions above, we just want to serialize them and marshal their
// arguments, send them over to the controller side and have them being
// executed there. The magic below takes care of turning each action into a
// function that returns the marshaled args.

// A DeferredAction is a bundle of Args and a method name. This is the marshaled
// version of a StateActions method call.
export interface DeferredAction<Args = {}> {
  type: string;
  args: Args;
}

// This type magic creates a type function DeferredActions<T> which takes a type
// T and 'maps' its attributes. For each attribute on T matching the signature:
// (state: StateDraft, args: Args) => void
// DeferredActions<T> has an attribute:
// (args: Args) => DeferredAction<Args>
type ActionFunction<Args> = (state: StateDraft, args: Args) => void;
type DeferredActionFunc<T> = T extends ActionFunction<infer Args>
  ? (args: Args) => DeferredAction<Args>
  : never;
type DeferredActions<C> = {
  [P in keyof C]: DeferredActionFunc<C[P]>;
};

// Actions is an implementation of DeferredActions<typeof StateActions>.
// (since StateActions is a variable not a type we have to do
// 'typeof StateActions' to access the (unnamed) type of StateActions).
// It's a Proxy such that any attribute access returns a function:
// (args) => {return {type: ATTRIBUTE_NAME, args};}
export const Actions =
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  new Proxy<DeferredActions<typeof StateActions>>({} as any, {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    get(_: any, prop: string, _2: any) {
      return (args: {}): DeferredAction<{}> => {
        return {
          type: prop,
          args,
        };
      };
    },
  });
