// 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 * as m from 'mithril';

import {EngineProxy} from '../common/engine';
import {QueryResponse, runQuery} from '../common/queries';

import {globals} from './globals';
import {createPage} from './pages';


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

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

// 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 queryResponse?: QueryResponse;

  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`;
    runQuery(query, engine).then((resp: QueryResponse) => {
      this.queryResponse = resp;
      globals.rafScheduler.scheduleFullRedraw();
    });
  }

  view({attrs}: m.CVnode<StatsSectionAttrs>) {
    const resp = this.queryResponse;
    if (resp === undefined || resp.totalRowCount === 0) {
      return m('');
    }
    if (resp.error) throw new Error(resp.error);

    const tableRows = [];
    for (const row of resp.rows) {
      const help = [];
      if (row.description) {
        help.push(m('i.material-icons.contextual-help', 'help_outline'));
      }
      const idx = row.idx !== '' ? `[${row.idx}]` : '';
      tableRows.push(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));
  }
}

class TraceMetadata implements m.ClassComponent {
  private queryResponse?: QueryResponse;

  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`;
    runQuery(query, engine).then((resp: QueryResponse) => {
      this.queryResponse = resp;
      globals.rafScheduler.scheduleFullRedraw();
    });
  }


  view() {
    const resp = this.queryResponse;
    if (resp === undefined || resp.totalRowCount === 0) {
      return m('');
    }

    const tableRows = [];
    for (const row of resp.rows) {
      tableRows.push(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),
            ),
    );
  }
}

class AndroidGameInterventionList implements m.ClassComponent {
  private queryResponse?: QueryResponse;

  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`;
    runQuery(query, engine).then((resp: QueryResponse) => {
      this.queryResponse = resp;
      globals.rafScheduler.scheduleFullRedraw();
    });
  }


  view() {
    const resp = this.queryResponse;
    if (resp === undefined || resp.totalRowCount === 0) {
      return m('');
    }

    const tableRows = [];
    let standardInterventions = '';
    let perfInterventions = '';
    let batteryInterventions = '';
    for (const row of resp.rows) {
      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';
      }

      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';
      }

      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/+/master: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),
            ),
    );
  }
}

class PackageList implements m.ClassComponent {
  private queryResponse?: QueryResponse;

  constructor() {
    const engine = getEngine('StatsSection');
    if (engine === undefined) {
      return;
    }
    const query = `select package_name, version_code, debuggable,
                profileable_from_shell from package_list`;
    runQuery(query, engine).then((resp: QueryResponse) => {
      this.queryResponse = resp;
      globals.rafScheduler.scheduleFullRedraw();
    });
  }


  view() {
    const resp = this.queryResponse;
    if (resp === undefined || resp.totalRowCount === 0) {
      return m('');
    }

    const tableRows = [];
    for (const row of resp.rows) {
      tableRows.push(m(
          'tr',
          m('td.name', `${row.package_name}`),
          m('td', `${row.version_code}`),
          m('td',
            `${row.debuggable ? 'debuggable' : ''} ${
                row.profileable_from_shell ? 'profileable' : ''}`),
          ));
    }

    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(PackageList),
        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: '',

        }),
    );
  },
});
