// Copyright (C) 2023 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 {Trace} from '../../public/trace';
import {PerfettoPlugin} from '../../public/plugin';
import {addDebugSliceTrack} from '../../components/tracks/debug_tracks';

export default class implements PerfettoPlugin {
  static readonly id = 'com.android.AndroidNetwork';
  // Adds a debug track using the provided query and given columns. The columns
  // must be start with ts, dur, and a name column. The name column and all
  // following columns are shown as arguments in slice details.
  async addSimpleTrack(
    ctx: Trace,
    trackName: string,
    tableOrQuery: string,
    columns: string[],
  ): Promise<void> {
    await addDebugSliceTrack({
      trace: ctx,
      data: {
        sqlSource: `SELECT ${columns.join(',')} FROM ${tableOrQuery}`,
        columns: columns,
      },
      title: trackName,
      columns: {ts: columns[0], dur: columns[1], name: columns[2]},
      rawColumns: columns.slice(2),
    });
  }

  async onTraceLoad(ctx: Trace): Promise<void> {
    ctx.commands.registerCommand({
      id: 'com.android.AddBatteryEventsTrack',
      name: 'Add track: battery events',
      callback: async (trackNameArg) => {
        const trackName =
          typeof trackNameArg === 'string'
            ? trackNameArg
            : await ctx.omnibox.prompt('Battery Track');

        if (!trackName) return;

        await ctx.engine.query(`SELECT IMPORT('android.battery_stats');`);
        await this.addSimpleTrack(
          ctx,
          trackName,
          `(SELECT *
            FROM android_battery_stats_event_slices
            WHERE track_name = "${trackName}")`,
          ['ts', 'dur', 'str_value', 'int_value'],
        );
      },
    });

    ctx.commands.registerCommand({
      id: 'com.android.AddNetworkActivityTrack',
      name: 'Add track: network activity',
      callback: async (groupByArg, filterArg, trackNameArg) => {
        const groupby =
          typeof groupByArg === 'string'
            ? groupByArg
            : await ctx.omnibox.prompt('Group by', 'package_name');

        if (groupby === undefined) return;

        const filter =
          typeof filterArg === 'string'
            ? filterArg
            : await ctx.omnibox.prompt('Filter', 'TRUE');

        if (filter === undefined) return;

        const trackName =
          typeof trackNameArg === 'string' ? trackNameArg : 'Network Activity';

        const suffix = new Date().getTime();
        await ctx.engine.query(`
          SELECT RUN_METRIC(
            'android/network_activity_template.sql',
            'view_name', 'android_network_activity_${suffix}',
            'group_by',  '${groupby}',
            'filter',    '${filter}',
            'idle_ns',   '10e9',
            'quant_ns',  '3e9'
          );
        `);

        // The first group column is used for the slice name.
        const groupCols = groupby.replaceAll(' ', '').split(',');
        await this.addSimpleTrack(
          ctx,
          trackName,
          `android_network_activity_${suffix}`,
          ['ts', 'dur', ...groupCols, 'packet_length', 'packet_count'],
        );
      },
    });
  }
}
