// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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 {Engine} from '../common/engine';
import {slowlyCountRows} from '../common/query_iterator';
import {Area} from '../common/state';
import {fromNs, toNs} from '../common/time';
import {Flow} from '../frontend/globals';
import {
  ACTUAL_FRAMES_SLICE_TRACK_KIND,
  Config as ActualConfig
} from '../tracks/actual_frames/common';
import {
  Config as SliceConfig,
  SLICE_TRACK_KIND
} from '../tracks/chrome_slices/common';

import {Controller} from './controller';
import {globals} from './globals';

export interface FlowEventsControllerArgs {
  engine: Engine;
}

export class FlowEventsController extends Controller<'main'> {
  private lastSelectedSliceId?: number;
  private lastSelectedArea?: Area;
  private lastSelectedKind: 'CHROME_SLICE'|'AREA'|'NONE' = 'NONE';

  constructor(private args: FlowEventsControllerArgs) {
    super('main');
  }

  queryFlowEvents(query: string, callback: (flows: Flow[]) => void) {
    this.args.engine.query(query).then(res => {
      const flows: Flow[] = [];
      for (let i = 0; i < slowlyCountRows(res); i++) {
        const beginSliceId = res.columns[0].longValues![i];
        const beginTrackId = res.columns[1].longValues![i];
        const beginSliceName = res.columns[2].stringValues![i];
        const beginSliceCategory = res.columns[3].stringValues![i];
        const beginSliceStartTs = fromNs(res.columns[4].longValues![i]);
        const beginSliceEndTs = fromNs(res.columns[5].longValues![i]);
        const beginDepth = res.columns[6].longValues![i];

        const endSliceId = res.columns[7].longValues![i];
        const endTrackId = res.columns[8].longValues![i];
        const endSliceName = res.columns[9].stringValues![i];
        const endSliceCategory = res.columns[10].stringValues![i];
        const endSliceStartTs = fromNs(res.columns[11].longValues![i]);
        const endSliceEndTs = fromNs(res.columns[12].longValues![i]);
        const endDepth = res.columns[13].longValues![i];

        // Category and name present only in version 1 flow events
        // It is most likelly NULL for all other versions
        const category = res.columns[14].isNulls![i] ?
            undefined :
            res.columns[14].stringValues![i];
        const name = res.columns[15].isNulls![i] ?
            undefined :
            res.columns[15].stringValues![i];
        const id = res.columns[16].longValues![i];

        flows.push({
          id,
          begin: {
            trackId: beginTrackId,
            sliceId: beginSliceId,
            sliceName: beginSliceName,
            sliceCategory: beginSliceCategory,
            sliceStartTs: beginSliceStartTs,
            sliceEndTs: beginSliceEndTs,
            depth: beginDepth
          },
          end: {
            trackId: endTrackId,
            sliceId: endSliceId,
            sliceName: endSliceName,
            sliceCategory: endSliceCategory,
            sliceStartTs: endSliceStartTs,
            sliceEndTs: endSliceEndTs,
            depth: endDepth
          },
          category,
          name
        });
      }
      callback(flows);
    });
  }

  sliceSelected(sliceId: number) {
    if (this.lastSelectedKind === 'CHROME_SLICE' &&
        this.lastSelectedSliceId === sliceId) {
      return;
    }
    this.lastSelectedSliceId = sliceId;
    this.lastSelectedKind = 'CHROME_SLICE';

    const query = `
    select
      f.slice_out, t1.track_id, t1.name,
      t1.category, t1.ts, (t1.ts+t1.dur), t1.depth,
      f.slice_in, t2.track_id, t2.name,
      t2.category, t2.ts, (t2.ts+t2.dur), t2.depth,
      extract_arg(f.arg_set_id, 'cat'),
      extract_arg(f.arg_set_id, 'name'),
      f.id
    from directly_connected_flow(${sliceId}) f
    join slice t1 on f.slice_out = t1.slice_id
    join slice t2 on f.slice_in = t2.slice_id
    `;
    this.queryFlowEvents(
        query, (flows: Flow[]) => globals.publish('ConnectedFlows', flows));
  }

  areaSelected(areaId: string) {
    const area = globals.state.areas[areaId];
    if (this.lastSelectedKind === 'AREA' && this.lastSelectedArea &&
        this.lastSelectedArea.tracks.join(',') === area.tracks.join(',') &&
        this.lastSelectedArea.endSec === area.endSec &&
        this.lastSelectedArea.startSec === area.startSec) {
      return;
    }

    this.lastSelectedArea = area;
    this.lastSelectedKind = 'AREA';

    const trackIds: number[] = [];

    for (const uiTrackId of area.tracks) {
      const track = globals.state.tracks[uiTrackId];
      if (track === undefined) {
        continue;
      }
      if (track.kind === SLICE_TRACK_KIND) {
        trackIds.push((track.config as SliceConfig).trackId);
      } else if (track.kind === ACTUAL_FRAMES_SLICE_TRACK_KIND) {
        const actualConfig = track.config as ActualConfig;
        for (const trackId of actualConfig.trackIds) {
          trackIds.push(trackId);
        }
      }
    }

    const tracks = `(${trackIds.join(',')})`;

    const startNs = toNs(area.startSec);
    const endNs = toNs(area.endSec);

    const query = `
    select
      f.slice_out, t1.track_id, t1.name,
      t1.category, t1.ts, (t1.ts+t1.dur), t1.depth,
      f.slice_in, t2.track_id, t2.name,
      t2.category, t2.ts, (t2.ts+t2.dur), t2.depth,
      extract_arg(f.arg_set_id, 'cat'),
      extract_arg(f.arg_set_id, 'name'),
      f.id
    from flow f
    join slice t1 on f.slice_out = t1.slice_id
    join slice t2 on f.slice_in = t2.slice_id
    where
      (t1.track_id in ${tracks}
        and (t1.ts+t1.dur <= ${endNs} and t1.ts+t1.dur >= ${startNs}))
      or
      (t2.track_id in ${tracks}
        and (t2.ts <= ${endNs} and t2.ts >= ${startNs}))
    `;
    this.queryFlowEvents(
        query, (flows: Flow[]) => globals.publish('SelectedFlows', flows));
  }

  refreshVisibleFlows() {
    const selection = globals.state.currentSelection;
    if (!selection) {
      this.lastSelectedKind = 'NONE';
      globals.publish('ConnectedFlows', []);
      globals.publish('SelectedFlows', []);
      return;
    }

    if (selection && selection.kind === 'CHROME_SLICE') {
      this.sliceSelected(selection.id);
    } else {
      globals.publish('ConnectedFlows', []);
    }

    if (selection && selection.kind === 'AREA') {
      this.areaSelected(selection.areaId);
    } else {
      globals.publish('SelectedFlows', []);
    }
  }

  run() {
    this.refreshVisibleFlows();
  }
}
