// 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 {Trace} from '../../public/trace';
import {PerfettoPlugin} from '../../public/plugin';
import {addDebugSliceTrack} from '../../public/debug_tracks';

export default class implements PerfettoPlugin {
  static readonly id = 'dev.perfetto.AndroidClientServer';
  async onTraceLoad(ctx: Trace): Promise<void> {
    ctx.commands.registerCommand({
      id: 'dev.perfetto.AndroidClientServer#ThreadRuntimeIPC',
      name: 'Show dependencies in client server model',
      callback: async (sliceId) => {
        if (sliceId === undefined) {
          sliceId = prompt('Enter a slice id', '');
          if (sliceId === null) 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(
            ctx,
            {
              sqlSource: `
                SELECT ts, dur, name
                FROM __enhanced_binder_for_slice_${sliceId}
                WHERE binder_id = ${it.id}
              `,
            },
            it.name,
            {ts: 'ts', dur: 'dur', name: 'name'},
            [],
          );
        }
      },
    });
  }
}
