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