// 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 {
  error,
  isError,
  isPending,
  pending,
  Result,
  success,
} from '../base/result';
import {pluginManager, PluginManager} from '../common/plugins';
import {raf} from '../core/raf_scheduler';
import {MetricVisualisation} from '../public';
import {EngineProxy} from '../trace_processor/engine';
import {STR} from '../trace_processor/query_result';
import {Select} from '../widgets/select';
import {Spinner} from '../widgets/spinner';
import {VegaView} from '../widgets/vega_view';

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

type Format = 'json' | 'prototext' | 'proto';
const FORMATS: Format[] = ['json', 'prototext', 'proto'];

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

async function getMetrics(engine: EngineProxy): Promise<string[]> {
  const metrics: string[] = [];
  const metricsResult = await engine.query('select name from trace_metrics');
  for (const it = metricsResult.iter({name: STR}); it.valid(); it.next()) {
    metrics.push(it.name);
  }
  return metrics;
}

async function getMetric(
  engine: EngineProxy,
  metric: string,
  format: Format,
): Promise<string> {
  const result = await engine.computeMetric([metric], format);
  if (result instanceof Uint8Array) {
    return `Uint8Array<len=${result.length}>`;
  } else {
    return result;
  }
}

class MetricsController {
  engine: EngineProxy;
  plugins: PluginManager;
  private _metrics: string[];
  private _selected?: string;
  private _result: Result<string>;
  private _format: Format;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private _json: any;

  constructor(plugins: PluginManager, engine: EngineProxy) {
    this.plugins = plugins;
    this.engine = engine;
    this._metrics = [];
    this._result = success('');
    this._json = {};
    this._format = 'json';
    getMetrics(this.engine).then((metrics) => {
      this._metrics = metrics;
    });
  }

  get metrics(): string[] {
    return this._metrics;
  }

  get visualisations(): MetricVisualisation[] {
    return this.plugins
      .metricVisualisations()
      .filter((v) => v.metric === this.selected);
  }

  set selected(metric: string | undefined) {
    if (this._selected === metric) {
      return;
    }
    this._selected = metric;
    this.update();
  }

  get selected(): string | undefined {
    return this._selected;
  }

  set format(format: Format) {
    if (this._format === format) {
      return;
    }
    this._format = format;
    this.update();
  }

  get format(): Format {
    return this._format;
  }

  get result(): Result<string> {
    return this._result;
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  get resultAsJson(): any {
    return this._json;
  }

  private update() {
    const selected = this._selected;
    const format = this._format;
    if (selected === undefined) {
      this._result = success('');
      this._json = {};
    } else {
      this._result = pending();
      this._json = {};
      getMetric(this.engine, selected, format)
        .then((result) => {
          if (this._selected === selected && this._format === format) {
            this._result = success(result);
            if (format === 'json') {
              this._json = JSON.parse(result);
            }
          }
        })
        .catch((e) => {
          if (this._selected === selected && this._format === format) {
            this._result = error(e);
            this._json = {};
          }
        })
        .finally(() => {
          raf.scheduleFullRedraw();
        });
    }
    raf.scheduleFullRedraw();
  }
}

interface MetricResultAttrs {
  result: Result<string>;
}

class MetricResultView implements m.ClassComponent<MetricResultAttrs> {
  view({attrs}: m.CVnode<MetricResultAttrs>) {
    const result = attrs.result;
    if (isPending(result)) {
      return m(Spinner);
    }

    if (isError(result)) {
      return m('pre.metric-error', result.error);
    }

    return m('pre', result.data);
  }
}

interface MetricPickerAttrs {
  controller: MetricsController;
}

class MetricPicker implements m.ClassComponent<MetricPickerAttrs> {
  view({attrs}: m.CVnode<MetricPickerAttrs>) {
    const {controller} = attrs;
    return m(
      '.metrics-page-picker',
      m(
        Select,
        {
          value: controller.selected,
          oninput: (e: Event) => {
            if (!e.target) return;
            controller.selected = (e.target as HTMLSelectElement).value;
          },
        },
        controller.metrics.map((metric) =>
          m(
            'option',
            {
              value: metric,
              key: metric,
            },
            metric,
          ),
        ),
      ),
      m(
        Select,
        {
          oninput: (e: Event) => {
            if (!e.target) return;
            controller.format = (e.target as HTMLSelectElement).value as Format;
          },
        },
        FORMATS.map((f) => {
          return m('option', {
            selected: controller.format === f,
            key: f,
            value: f,
            label: f,
          });
        }),
      ),
    );
  }
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
interface MetricVizViewAttrs {
  visualisation: MetricVisualisation;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  data: any;
}

class MetricVizView implements m.ClassComponent<MetricVizViewAttrs> {
  view({attrs}: m.CVnode<MetricVizViewAttrs>) {
    return m(
      '',
      m(VegaView, {
        spec: attrs.visualisation.spec,
        data: {
          metric: attrs.data,
        },
      }),
    );
  }
}

class MetricPageContents implements m.ClassComponent {
  controller?: MetricsController;

  oncreate() {
    const engine = getEngine();
    if (engine !== undefined) {
      this.controller = new MetricsController(pluginManager, engine);
    }
  }

  view() {
    const controller = this.controller;
    if (controller === undefined) {
      return m('');
    }

    const json = controller.resultAsJson;

    return [
      m(MetricPicker, {
        controller,
      }),
      controller.format === 'json' &&
        controller.visualisations.map((visualisation) => {
          let data = json;
          for (const p of visualisation.path) {
            data = data[p] ?? [];
          }
          return m(MetricVizView, {visualisation, data});
        }),
      m(MetricResultView, {result: controller.result}),
    ];
  }
}

export const MetricsPage = createPage({
  view() {
    return m('.metrics-page', m(MetricPageContents));
  },
});
