// Copyright (C) 2019 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 {searchSegment} from '../base/binary_search';
import {assertUnreachable} from '../base/logging';
import {Actions} from '../common/actions';
import {globals} from './globals';
import {verticalScrollToTrack} from './scroll_helper';

function setToPrevious(current: number) {
  let index = current - 1;
  if (index < 0) {
    index = globals.currentSearchResults.totalResults - 1;
  }
  globals.dispatch(Actions.setSearchIndex({index}));
}

function setToNext(current: number) {
  const index = (current + 1) % globals.currentSearchResults.totalResults;
  globals.dispatch(Actions.setSearchIndex({index}));
}

export function executeSearch(reverse = false) {
  const index = globals.state.searchIndex;
  const vizWindow = globals.stateVisibleTime();
  const startNs = vizWindow.start;
  const endNs = vizWindow.end;
  const currentTs = globals.currentSearchResults.tses[index];

  // If the value of |globals.currentSearchResults.totalResults| is 0,
  // it means that the query is in progress or no results are found.
  if (globals.currentSearchResults.totalResults === 0) {
    return;
  }

  // If this is a new search or the currentTs is not in the viewport,
  // select the first/last item in the viewport.
  if (
    index === -1 ||
    (currentTs !== -1n && (currentTs < startNs || currentTs > endNs))
  ) {
    if (reverse) {
      const [smaller] = searchSegment(globals.currentSearchResults.tses, endNs);
      // If there is no item in the viewport just go to the previous.
      if (smaller === -1) {
        setToPrevious(index);
      } else {
        globals.dispatch(Actions.setSearchIndex({index: smaller}));
      }
    } else {
      const [, larger] = searchSegment(
        globals.currentSearchResults.tses,
        startNs,
      );
      // If there is no item in the viewport just go to the next.
      if (larger === -1) {
        setToNext(index);
      } else {
        globals.dispatch(Actions.setSearchIndex({index: larger}));
      }
    }
  } else {
    // If the currentTs is in the viewport, increment the index.
    if (reverse) {
      setToPrevious(index);
    } else {
      setToNext(index);
    }
  }
  selectCurrentSearchResult();
}

function selectCurrentSearchResult() {
  const searchIndex = globals.state.searchIndex;
  const source = globals.currentSearchResults.sources[searchIndex];
  const currentId = globals.currentSearchResults.eventIds[searchIndex];
  const trackKey = globals.currentSearchResults.trackKeys[searchIndex];

  if (currentId === undefined) return;

  switch (source) {
    case 'track':
      verticalScrollToTrack(trackKey, true);
      break;
    case 'cpu':
      globals.setLegacySelection(
        {
          kind: 'SLICE',
          id: currentId,
          trackKey,
        },
        {
          clearSearch: false,
          pendingScrollId: currentId,
          switchToCurrentSelectionTab: true,
        },
      );
      break;
    case 'log':
      globals.setLegacySelection(
        {
          kind: 'LOG',
          id: currentId,
          trackKey,
        },
        {
          clearSearch: false,
          pendingScrollId: currentId,
          switchToCurrentSelectionTab: true,
        },
      );
      break;
    case 'slice':
      // Search results only include slices from the slice table for now.
      // When we include annotations we need to pass the correct table.
      globals.setLegacySelection(
        {
          kind: 'CHROME_SLICE',
          id: currentId,
          trackKey,
          table: 'slice',
        },
        {
          clearSearch: false,
          pendingScrollId: currentId,
          switchToCurrentSelectionTab: true,
        },
      );
      break;
    default:
      assertUnreachable(source);
  }
}
