// 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 {NUM, STR} from '../../trace_processor/query_result';
import type {Trace} from '../../public/trace';
import type {PerfettoPlugin} from '../../public/plugin';
import {addDebugSliceTrack} from '../../components/tracks/debug_tracks';

export default class implements PerfettoPlugin {
  static readonly id = 'com.android.AndroidClientServer';
  async onTraceLoad(ctx: Trace): Promise<void> {
    ctx.commands.registerCommand({
      id: 'com.android.ShowClientServerDependencies',
      name: 'Show dependencies in client server model',
      callback: async (sliceId) => {
        if (sliceId === undefined) {
          sliceId = await ctx.omnibox.prompt('Enter a slice id');
          if (sliceId === undefined) return;
        }
        await ctx.engine.query(`
          include perfetto module android.binder;
          include perfetto module graphs.search;

          create or replace perfetto table __binder_for_slice_${sliceId} as
          with s as materialized (
            select slice.id, ts, ts + dur as ts_end, dur, upid
            from thread_slice slice
            where slice.id = ${sliceId}
          ),
          child_binder_txns_for_slice as materialized (
            select
              (select id from s) as source_node_id,
              binder_txn_id as dest_node_id
            from descendant_slice((select id from s)) as desc
            join android_binder_txns txns on desc.id = txns.binder_txn_id
          ),
          binder_txns_in_slice_intervals as materialized (
            select
              binder_txn_id as source_node_id,
              binder_reply_id as dest_node_id
            from android_binder_txns
            where client_ts > (select ts from s)
              and client_ts < (select ts + dur from s)
          ),
          nested_binder_txns_in_slice_interval as materialized (
            select
              parent.binder_reply_id as source_node_id,
              child.binder_txn_id as dest_node_id
            from android_binder_txns parent
            join descendant_slice(parent.binder_reply_id) desc
            join android_binder_txns child on desc.id = child.binder_txn_id
            where parent.server_ts > (select ts from s)
              and parent.server_ts < (select ts + dur from s)
          ),
          all_binder_txns_considered as materialized (
            select * from child_binder_txns_for_slice
            union
            select * from binder_txns_in_slice_intervals
            union
            select * from nested_binder_txns_in_slice_interval
          )
          select
            dfs.node_id as id,
            coalesce(client.client_ts, server.client_ts, slice.ts) as ts,
            coalesce(client.client_dur, server.client_dur, slice.dur) as dur,
            coalesce(
              client.aidl_name,
              server.aidl_name,
              iif(
                server.binder_reply_id is not null,
                coalesce(
                  server.server_process,
                  server.server_thread,
                  'Unknown server'
                ),
                slice.name
              )
            ) name,
            coalesce(
              client.client_utid,
              server.server_utid,
              thread_track.utid
            ) as utid,
            case
              when client.binder_txn_id is not null then 'client'
              when server.binder_reply_id is not null then 'server'
              else 'slice'
            end as slice_type,
            coalesce(client.is_sync, server.is_sync, true) as is_sync
          from graph_reachable_dfs!(
            all_binder_txns_considered,
            (select id as node_id from s)
          ) dfs
          join slice on dfs.node_id = slice.id
          join thread_track on slice.track_id = thread_track.id
          left join android_binder_txns client on dfs.node_id = client.binder_txn_id
          left join android_binder_txns server on dfs.node_id = server.binder_reply_id
          order by ts;
        `);
        await ctx.engine.query(`
          include perfetto module intervals.intersect;

          create or replace perfetto table __enhanced_binder_for_slice_${sliceId} as
          with foo as (
            select
              bfs.id as binder_id,
              bfs.name as binder_name,
              ii.ts,
              ii.dur,
              tstate.utid,
              thread.upid,
              tstate.cpu,
              tstate.state,
              tstate.io_wait,
              (
                select name
                from thread_slice tslice
                where tslice.utid = tstate.utid and tslice.ts < ii.ts
                order by ts desc
                limit 1
              ) as enclosing_slice_name
            from _interval_intersect!(
              (
                select id, ts, dur
                from __binder_for_slice_${sliceId}
                where slice_type IN ('slice', 'server')
                  and is_sync
                  and dur > 0
              ),
              (
                select id, ts, dur
                from thread_state tstate
                where
                  tstate.utid in (
                    select distinct utid
                    from __binder_for_slice_${sliceId}
                    where
                      slice_type IN ('slice', 'server')
                      and is_sync
                      and dur > 0
                  )
                  and dur > 0
              ),
              ()
            ) ii
            join __binder_for_slice_${sliceId} bfs on ii.id_0 = bfs.id
            join thread_state tstate on ii.id_1 = tstate.id
            join thread using (utid)
            where bfs.utid = tstate.utid
          )
          select
            *,
            case
              when state = 'S' and enclosing_slice_name = 'binder transaction' then 'Waiting for server'
              when state = 'S' and enclosing_slice_name GLOB 'Lock*' then 'Waiting for lock'
              when state = 'S' and enclosing_slice_name GLOB 'Monitor*' then 'Waiting for contention'
              when state = 'S' then 'Sleeping'
              when state = 'R' then 'Waiting for CPU'
              when state = 'Running' then 'Running on CPU ' || foo.cpu
              when state GLOB 'R*' then 'Runnable'
              when state GLOB 'D*' and io_wait then 'IO'
              when state GLOB 'D*' and not io_wait then 'Unint-sleep'
            end as name
          from foo
          order by binder_id;
        `);

        const res = await ctx.engine.query(`
          select id, name
          from __binder_for_slice_${sliceId} bfs
          where slice_type IN ('slice', 'server')
            and dur > 0
          order by ts
        `);
        const it = res.iter({
          id: NUM,
          name: STR,
        });
        for (; it.valid(); it.next()) {
          await addDebugSliceTrack({
            trace: ctx,
            data: {
              sqlSource: `
                SELECT ts, dur, name
                FROM __enhanced_binder_for_slice_${sliceId}
                WHERE binder_id = ${it.id}
              `,
            },
            title: it.name,
          });
        }
      },
    });
  }
}
