// 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 {runQuery} from '../../common/queries';
import {addDebugSliceTrack} from '../../public';
import {Plugin, PluginContextTrace, PluginDescriptor} from '../../public';

const JANK_CUJ_QUERY_PRECONDITIONS = `
  SELECT RUN_METRIC('android/android_jank_cuj.sql');
  SELECT RUN_METRIC('android/jank/internal/counters.sql');
  INCLUDE PERFETTO MODULE android.critical_blocking_calls;
`;

const JANK_CUJ_QUERY = `
    SELECT
      CASE
        WHEN
          EXISTS(
              SELECT 1
              FROM slice AS cuj_state_marker
                     JOIN track marker_track
                          ON marker_track.id = cuj_state_marker.track_id
              WHERE
                cuj_state_marker.ts >= cuj.ts
                AND cuj_state_marker.ts + cuj_state_marker.dur <= cuj.ts + cuj.dur
                AND
                ( /* e.g. J<CUJ_NAME>#FT#cancel#0 this for backward compatibility */
                      cuj_state_marker.name GLOB(cuj.name || '#FT#cancel*')
                    OR (marker_track.name = cuj.name AND cuj_state_marker.name GLOB 'FT#cancel*')
                  )
            )
          THEN ' ❌ '
        WHEN
          EXISTS(
              SELECT 1
              FROM slice AS cuj_state_marker
                     JOIN track marker_track
                          ON marker_track.id = cuj_state_marker.track_id
              WHERE
                cuj_state_marker.ts >= cuj.ts
                AND cuj_state_marker.ts + cuj_state_marker.dur <= cuj.ts + cuj.dur
                AND
                ( /* e.g. J<CUJ_NAME>#FT#end#0 this for backward compatibility */
                      cuj_state_marker.name GLOB(cuj.name || '#FT#end*')
                    OR (marker_track.name = cuj.name AND cuj_state_marker.name GLOB 'FT#end*')
                  )
            )
          THEN ' ✅ '
        ELSE NULL
        END || cuj.name AS name,
      total_frames,
      missed_app_frames,
      missed_sf_frames,
      sf_callback_missed_frames,
      hwui_callback_missed_frames,
      cuj_layer.layer_name,
      /* Boundaries table doesn't contain ts and dur when a CUJ didn't complete successfully.
        In that case we still want to show that it was canceled, so let's take the slice timestamps. */
      CASE WHEN boundaries.ts IS NOT NULL THEN boundaries.ts ELSE cuj.ts END AS ts,
      CASE WHEN boundaries.dur IS NOT NULL THEN boundaries.dur ELSE cuj.dur END AS dur,
      cuj.track_id,
      cuj.slice_id
    FROM slice AS cuj
           JOIN process_track AS pt ON cuj.track_id = pt.id
           LEFT JOIN android_jank_cuj jc
                     ON pt.upid = jc.upid AND cuj.name = jc.cuj_slice_name AND cuj.ts = jc.ts
           LEFT JOIN android_jank_cuj_main_thread_cuj_boundary boundaries using (cuj_id)
           LEFT JOIN android_jank_cuj_layer_name cuj_layer USING (cuj_id)
           LEFT JOIN android_jank_cuj_counter_metrics USING (cuj_id)
    WHERE cuj.name GLOB 'J<*>'
      AND cuj.dur > 0
`;

const JANK_COLUMNS = [
  'name',
  'total_frames',
  'missed_app_frames',
  'missed_sf_frames',
  'sf_callback_missed_frames',
  'hwui_callback_missed_frames',
  'layer_name',
  'ts',
  'dur',
  'track_id',
  'slice_id',
];

const LATENCY_CUJ_QUERY = `
    SELECT
      CASE
        WHEN
          EXISTS(
              SELECT 1
              FROM slice AS cuj_state_marker
                     JOIN track marker_track
                          ON marker_track.id = cuj_state_marker.track_id
              WHERE
                cuj_state_marker.ts >= cuj.ts
                AND cuj_state_marker.ts + cuj_state_marker.dur <= cuj.ts + cuj.dur
                AND marker_track.name = cuj.name AND (
                    cuj_state_marker.name GLOB 'cancel' 
                    OR cuj_state_marker.name GLOB 'timeout')
            )
          THEN ' ❌ '
        ELSE ' ✅ '
        END || cuj.name AS name,
      cuj.dur / 1e6 as dur_ms,
      cuj.ts,
      cuj.dur,
      cuj.track_id,
      cuj.slice_id
    FROM slice AS cuj
           JOIN process_track AS pt
                ON cuj.track_id = pt.id
    WHERE cuj.name GLOB 'L<*>'
      AND cuj.dur > 0
`;

const LATENCY_COLUMNS = ['name', 'dur_ms', 'ts', 'dur', 'track_id', 'slice_id'];

const BLOCKING_CALLS_DURING_CUJS_QUERY = `
    SELECT
      s.id AS slice_id,
      s.name,
      max(s.ts, cuj.ts) AS ts,
      min(s.ts + s.dur, cuj.ts_end) as ts_end,
      min(s.ts + s.dur, cuj.ts_end) - max(s.ts, cuj.ts) AS dur,
      cuj.cuj_id,
      cuj.cuj_name,
      s.process_name,
      s.upid,
      s.utid,
      'slice' AS table_name
    FROM _android_critical_blocking_calls s
      JOIN  android_jank_cuj cuj
      -- only when there is an overlap
      ON s.ts + s.dur > cuj.ts AND s.ts < cuj.ts_end
          -- and are from the same process
          AND s.upid = cuj.upid
`;

const BLOCKING_CALLS_DURING_CUJS_COLUMNS = [
  'slice_id',
  'name',
  'ts',
  'cuj_ts',
  'dur',
  'cuj_id',
  'cuj_name',
  'process_name',
  'upid',
  'utid',
  'table_name',
];

class AndroidCujs implements Plugin {
  async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
    ctx.registerCommand({
      id: 'dev.perfetto.AndroidCujs#PinJankCUJs',
      name: 'Add track: Android jank CUJs',
      callback: () => {
        runQuery(JANK_CUJ_QUERY_PRECONDITIONS, ctx.engine).then(() => {
          addDebugSliceTrack(
            ctx.engine,
            {
              sqlSource: JANK_CUJ_QUERY,
              columns: JANK_COLUMNS,
            },
            'Jank CUJs',
            {ts: 'ts', dur: 'dur', name: 'name'},
            JANK_COLUMNS,
          );
        });
      },
    });

    ctx.registerCommand({
      id: 'dev.perfetto.AndroidCujs#ListJankCUJs',
      name: 'Run query: Android jank CUJs',
      callback: () => {
        runQuery(JANK_CUJ_QUERY_PRECONDITIONS, ctx.engine).then(() =>
          ctx.tabs.openQuery(JANK_CUJ_QUERY, 'Android Jank CUJs'),
        );
      },
    });

    ctx.registerCommand({
      id: 'dev.perfetto.AndroidCujs#PinLatencyCUJs',
      name: 'Add track: Android latency CUJs',
      callback: () => {
        addDebugSliceTrack(
          ctx.engine,
          {
            sqlSource: LATENCY_CUJ_QUERY,
            columns: LATENCY_COLUMNS,
          },
          'Latency CUJs',
          {ts: 'ts', dur: 'dur', name: 'name'},
          [],
        );
      },
    });

    ctx.registerCommand({
      id: 'dev.perfetto.AndroidCujs#ListLatencyCUJs',
      name: 'Run query: Android Latency CUJs',
      callback: () =>
        ctx.tabs.openQuery(LATENCY_CUJ_QUERY, 'Android Latency CUJs'),
    });

    ctx.registerCommand({
      id: 'dev.perfetto.AndroidCujs#PinBlockingCalls',
      name: 'Add track: Android Blocking calls during CUJs',
      callback: () => {
        runQuery(JANK_CUJ_QUERY_PRECONDITIONS, ctx.engine).then(() =>
          addDebugSliceTrack(
            ctx.engine,
            {
              sqlSource: BLOCKING_CALLS_DURING_CUJS_QUERY,
              columns: BLOCKING_CALLS_DURING_CUJS_COLUMNS,
            },
            'Blocking calls during CUJs',
            {ts: 'ts', dur: 'dur', name: 'name'},
            BLOCKING_CALLS_DURING_CUJS_COLUMNS,
          ),
        );
      },
    });
  }
}

export const plugin: PluginDescriptor = {
  pluginId: 'dev.perfetto.AndroidCujs',
  plugin: AndroidCujs,
};
