// Copyright (C) 2020 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 m from 'mithril';
import {raf} from '../core/raf_scheduler';
import {Engine} from '../trace_processor/engine';
import {globals} from './globals';
import {createPage} from './pages';
import {QueryResult, UNKNOWN} from '../trace_processor/query_result';

function getEngine(name: string): Engine | undefined {
  const currentEngine = globals.getCurrentEngine();
  if (currentEngine === undefined) return undefined;
  const engineId = currentEngine.id;
  return globals.engines.get(engineId)?.getProxy(name);
}

/**
 * Extracts and copies fields from a source object based on the keys present in
 * a spec object, effectively creating a new object that includes only the
 * fields that are present in the spec object.
 *
 * @template S - A type representing the spec object, a subset of T.
 * @template T - A type representing the source object, a superset of S.
 *
 * @param {T} source - The source object containing the full set of properties.
 * @param {S} spec - The specification object whose keys determine which fields
 * should be extracted from the source object.
 *
 * @returns {S} A new object containing only the fields from the source object
 * that are also present in the specification object.
 *
 * @example
 * const fullObject = { foo: 123, bar: '123', baz: true };
 * const spec = { foo: 0, bar: '' };
 * const result = pickFields(fullObject, spec);
 * console.log(result); // Output: { foo: 123, bar: '123' }
 */
function pickFields<S extends Record<string, unknown>, T extends S>(
  source: T,
  spec: S,
): S {
  const result: Record<string, unknown> = {};
  for (const key of Object.keys(spec)) {
    result[key] = source[key];
  }
  return result as S;
}

interface StatsSectionAttrs {
  title: string;
  subTitle: string;
  sqlConstraints: string;
  cssClass: string;
  queryId: string;
}

const statsSpec = {
  name: UNKNOWN,
  value: UNKNOWN,
  description: UNKNOWN,
  idx: UNKNOWN,
  severity: UNKNOWN,
  source: UNKNOWN,
};

type StatsSectionRow = typeof statsSpec;

// Generic class that generate a <section> + <table> from the stats table.
// The caller defines the query constraint, title and styling.
// Used for errors, data losses and debugging sections.
class StatsSection implements m.ClassComponent<StatsSectionAttrs> {
  private data?: StatsSectionRow[];

  constructor({attrs}: m.CVnode<StatsSectionAttrs>) {
    const engine = getEngine('StatsSection');
    if (engine === undefined) {
      return;
    }
    const query = `
      select
        name,
        value,
        cast(ifnull(idx, '') as text) as idx,
        description,
        severity,
        source from stats
      where ${attrs.sqlConstraints || '1=1'}
      order by name, idx
    `;

    engine.query(query).then((resp) => {
      const data: StatsSectionRow[] = [];
      const it = resp.iter(statsSpec);
      for (; it.valid(); it.next()) {
        data.push(pickFields(it, statsSpec));
      }
      this.data = data;

      raf.scheduleFullRedraw();
    });
  }

  view({attrs}: m.CVnode<StatsSectionAttrs>) {
    const data = this.data;
    if (data === undefined || data.length === 0) {
      return m('');
    }

    const tableRows = data.map((row) => {
      const help = [];
      if (Boolean(row.description)) {
        help.push(m('i.material-icons.contextual-help', 'help_outline'));
      }
      const idx = row.idx !== '' ? `[${row.idx}]` : '';
      return m(
        'tr',
        m('td.name', {title: row.description}, `${row.name}${idx}`, help),
        m('td', `${row.value}`),
        m('td', `${row.severity} (${row.source})`),
      );
    });

    return m(
      `section${attrs.cssClass}`,
      m('h2', attrs.title),
      m('h3', attrs.subTitle),
      m(
        'table',
        m('thead', m('tr', m('td', 'Name'), m('td', 'Value'), m('td', 'Type'))),
        m('tbody', tableRows),
      ),
    );
  }
}

class MetricErrors implements m.ClassComponent {
  view() {
    if (!globals.metricError) return;
    return m(
      `section.errors`,
      m('h2', `Metric Errors`),
      m('h3', `One or more metrics were not computed successfully:`),
      m('div.metric-error', globals.metricError),
    );
  }
}

const traceMetadataRowSpec = {name: UNKNOWN, value: UNKNOWN};

type TraceMetadataRow = typeof traceMetadataRowSpec;

class TraceMetadata implements m.ClassComponent {
  private data?: TraceMetadataRow[];

  constructor() {
    const engine = getEngine('StatsSection');
    if (engine === undefined) {
      return;
    }
    const query = `
      with metadata_with_priorities as (
        select
          name,
          ifnull(str_value, cast(int_value as text)) as value,
          name in (
            "trace_size_bytes",
            "cr-os-arch",
            "cr-os-name",
            "cr-os-version",
            "cr-physical-memory",
            "cr-product-version",
            "cr-hardware-class"
          ) as priority
        from metadata
      )
      select
        name,
        value
      from metadata_with_priorities
      order by
        priority desc,
        name
    `;

    engine.query(query).then((resp: QueryResult) => {
      const tableRows: TraceMetadataRow[] = [];
      const it = resp.iter(traceMetadataRowSpec);
      for (; it.valid(); it.next()) {
        tableRows.push(pickFields(it, traceMetadataRowSpec));
      }
      this.data = tableRows;
      raf.scheduleFullRedraw();
    });
  }

  view() {
    const data = this.data;
    if (data === undefined || data.length === 0) {
      return m('');
    }

    const tableRows = data.map((row) => {
      return m('tr', m('td.name', `${row.name}`), m('td', `${row.value}`));
    });

    return m(
      'section',
      m('h2', 'System info and metadata'),
      m(
        'table',
        m('thead', m('tr', m('td', 'Name'), m('td', 'Value'))),
        m('tbody', tableRows),
      ),
    );
  }
}

const androidGameInterventionRowSpec = {
  package_name: UNKNOWN,
  uid: UNKNOWN,
  current_mode: UNKNOWN,
  standard_mode_supported: UNKNOWN,
  standard_mode_downscale: UNKNOWN,
  standard_mode_use_angle: UNKNOWN,
  standard_mode_fps: UNKNOWN,
  perf_mode_supported: UNKNOWN,
  perf_mode_downscale: UNKNOWN,
  perf_mode_use_angle: UNKNOWN,
  perf_mode_fps: UNKNOWN,
  battery_mode_supported: UNKNOWN,
  battery_mode_downscale: UNKNOWN,
  battery_mode_use_angle: UNKNOWN,
  battery_mode_fps: UNKNOWN,
};

type AndroidGameInterventionRow = typeof androidGameInterventionRowSpec;

class AndroidGameInterventionList implements m.ClassComponent {
  private data?: AndroidGameInterventionRow[];

  constructor() {
    const engine = getEngine('StatsSection');
    if (engine === undefined) {
      return;
    }
    const query = `
      select
        package_name,
        uid,
        current_mode,
        standard_mode_supported,
        standard_mode_downscale,
        standard_mode_use_angle,
        standard_mode_fps,
        perf_mode_supported,
        perf_mode_downscale,
        perf_mode_use_angle,
        perf_mode_fps,
        battery_mode_supported,
        battery_mode_downscale,
        battery_mode_use_angle,
        battery_mode_fps
      from android_game_intervention_list
    `;

    engine.query(query).then((resp) => {
      const data: AndroidGameInterventionRow[] = [];
      const it = resp.iter(androidGameInterventionRowSpec);
      for (; it.valid(); it.next()) {
        data.push(pickFields(it, androidGameInterventionRowSpec));
      }
      this.data = data;
      raf.scheduleFullRedraw();
    });
  }

  view() {
    const data = this.data;
    if (data === undefined || data.length === 0) {
      return m('');
    }

    const tableRows = [];
    let standardInterventions = '';
    let perfInterventions = '';
    let batteryInterventions = '';

    for (const row of data) {
      // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
      if (row.standard_mode_supported) {
        standardInterventions = `angle=${row.standard_mode_use_angle},downscale=${row.standard_mode_downscale},fps=${row.standard_mode_fps}`;
      } else {
        standardInterventions = 'Not supported';
      }

      // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
      if (row.perf_mode_supported) {
        perfInterventions = `angle=${row.perf_mode_use_angle},downscale=${row.perf_mode_downscale},fps=${row.perf_mode_fps}`;
      } else {
        perfInterventions = 'Not supported';
      }

      // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
      if (row.battery_mode_supported) {
        batteryInterventions = `angle=${row.battery_mode_use_angle},downscale=${row.battery_mode_downscale},fps=${row.battery_mode_fps}`;
      } else {
        batteryInterventions = 'Not supported';
      }
      // Game mode numbers are defined in
      // https://cs.android.com/android/platform/superproject/+/main:frameworks/base/core/java/android/app/GameManager.java;l=68
      if (row.current_mode === 1) {
        row.current_mode = 'Standard';
      } else if (row.current_mode === 2) {
        row.current_mode = 'Performance';
      } else if (row.current_mode === 3) {
        row.current_mode = 'Battery';
      }
      tableRows.push(
        m(
          'tr',
          m('td.name', `${row.package_name}`),
          m('td', `${row.current_mode}`),
          m('td', standardInterventions),
          m('td', perfInterventions),
          m('td', batteryInterventions),
        ),
      );
    }

    return m(
      'section',
      m('h2', 'Game Intervention List'),
      m(
        'table',
        m(
          'thead',
          m(
            'tr',
            m('td', 'Name'),
            m('td', 'Current mode'),
            m('td', 'Standard mode interventions'),
            m('td', 'Performance mode interventions'),
            m('td', 'Battery mode interventions'),
          ),
        ),
        m('tbody', tableRows),
      ),
    );
  }
}

const packageDataSpec = {
  packageName: UNKNOWN,
  versionCode: UNKNOWN,
  debuggable: UNKNOWN,
  profileableFromShell: UNKNOWN,
};

type PackageData = typeof packageDataSpec;

class PackageListSection implements m.ClassComponent {
  private packageList?: PackageData[];

  constructor() {
    const engine = getEngine('StatsSection');
    if (engine === undefined) {
      return;
    }
    this.loadData(engine);
  }

  private async loadData(engine: Engine): Promise<void> {
    const query = `
      select
        package_name as packageName,
        version_code as versionCode,
        debuggable,
        profileable_from_shell as profileableFromShell
      from package_list
    `;

    const packageList: PackageData[] = [];
    const result = await engine.query(query);
    const it = result.iter(packageDataSpec);
    for (; it.valid(); it.next()) {
      packageList.push(pickFields(it, packageDataSpec));
    }

    this.packageList = packageList;
    raf.scheduleFullRedraw();
  }

  view() {
    const packageList = this.packageList;
    if (packageList === undefined || packageList.length === 0) {
      return undefined;
    }

    const tableRows = packageList.map((it) => {
      return m(
        'tr',
        m('td.name', `${it.packageName}`),
        m('td', `${it.versionCode}`),
        /* eslint-disable @typescript-eslint/strict-boolean-expressions */
        m(
          'td',
          `${it.debuggable ? 'debuggable' : ''} ${
            it.profileableFromShell ? 'profileable' : ''
          }`,
        ),
        /* eslint-enable */
      );
    });

    return m(
      'section',
      m('h2', 'Package list'),
      m(
        'table',
        m(
          'thead',
          m('tr', m('td', 'Name'), m('td', 'Version code'), m('td', 'Flags')),
        ),
        m('tbody', tableRows),
      ),
    );
  }
}

export const TraceInfoPage = createPage({
  view() {
    return m(
      '.trace-info-page',
      m(MetricErrors),
      m(StatsSection, {
        queryId: 'info_errors',
        title: 'Import errors',
        cssClass: '.errors',
        subTitle: `The following errors have been encountered while importing the
               trace. These errors are usually non-fatal but indicate that one
               or more tracks might be missing or showing erroneous data.`,
        sqlConstraints: `severity = 'error' and value > 0`,
      }),
      m(StatsSection, {
        queryId: 'info_data_losses',
        title: 'Data losses',
        cssClass: '.errors',
        subTitle: `These counters are collected at trace recording time. The trace
               data for one or more data sources was dropped and hence some
               track contents will be incomplete.`,
        sqlConstraints: `severity = 'data_loss' and value > 0`,
      }),
      m(TraceMetadata),
      m(PackageListSection),
      m(AndroidGameInterventionList),
      m(StatsSection, {
        queryId: 'info_all',
        title: 'Debugging stats',
        cssClass: '',
        subTitle: `Debugging statistics such as trace buffer usage and metrics
                     coming from the TraceProcessor importer stages.`,
        sqlConstraints: '',
      }),
    );
  },
});
