// 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 m from 'mithril';
import {v4 as uuidv4} from 'uuid';

import {assertExists} from '../base/logging';
import {duration, time} from '../base/time';
import {PanelSize} from '../frontend/panel';
import {NewTrackArgs} from '../frontend/track';
import {SliceRect} from '../public';
import {EngineProxy} from '../trace_processor/engine';

import {TrackHelperLEGACY} from './track_helper';

export {Store} from '../frontend/store';
export {EngineProxy} from '../trace_processor/engine';
export {
  LONG,
  LONG_NULL,
  NUM,
  NUM_NULL,
  STR,
  STR_NULL,
} from '../trace_processor/query_result';

// This is an adapter to convert old style controller based tracks to new style
// tracks.
export class TrackWithControllerAdapter<Config, Data> extends
    TrackHelperLEGACY<Data> {
  private track: TrackAdapter<Config, Data>;
  private controller: TrackControllerAdapter<Config, Data>;
  private isSetup = false;

  constructor(
      engine: EngineProxy, trackKey: string, config: Config,
      Track: TrackAdapterClass<Config, Data>,
      Controller: TrackControllerAdapterClass<Config, Data>) {
    super();
    const args: NewTrackArgs = {
      trackKey,
      engine,
    };
    this.track = new Track(args);
    this.track.setConfig(config);
    this.track.setDataSource(() => this.data);
    this.controller = new Controller(config, engine);
  }

  onDestroy(): void {
    this.track.onDestroy();
    this.controller.onDestroy();
    super.onDestroy();
  }

  getSliceRect(tStart: time, tEnd: time, depth: number): SliceRect|undefined {
    return this.track.getSliceRect(tStart, tEnd, depth);
  }

  getHeight(): number {
    return this.track.getHeight();
  }

  getTrackShellButtons(): m.Children {
    return this.track.getTrackShellButtons();
  }

  onMouseMove(position: {x: number; y: number;}): void {
    this.track.onMouseMove(position);
  }

  onMouseClick(position: {x: number; y: number;}): boolean {
    return this.track.onMouseClick(position);
  }

  onMouseOut(): void {
    this.track.onMouseOut();
  }

  onFullRedraw(): void {
    this.track.onFullRedraw();
  }

  async onBoundsChange(start: time, end: time, resolution: duration):
      Promise<Data> {
    if (!this.isSetup) {
      await this.controller.onSetup();
      this.isSetup = true;
    }
    return await this.controller.onBoundsChange(start, end, resolution);
  }

  renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void {
    this.track.renderCanvas(ctx, size);
  }
}

// Extend from this class instead of `Track` to use existing track
// implementations with `TrackWithControllerAdapter`.
export abstract class TrackAdapter<Config, Data> {
  private _config?: Config;
  private dataSource?: () => Data | undefined;
  protected trackKey: string;

  get config(): Config {
    return assertExists(this._config);
  }

  setConfig(config: Config) {
    this._config = config;
  }

  data(): Data|undefined {
    return this.dataSource && this.dataSource();
  }

  // A callback used to fetch the latest data
  setDataSource(dataSource: () => Data | undefined) {
    this.dataSource = dataSource;
  }

  constructor(args: NewTrackArgs) {
    this.trackKey = args.trackKey;
  }

  abstract renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize): void;

  getSliceRect(_tStart: time, _tEnd: time, _depth: number): SliceRect
      |undefined {
    return undefined;
  }

  getHeight(): number {
    return 40;
  }

  getTrackShellButtons(): m.Children {
    return [];
  }

  onMouseMove(_position: {x: number, y: number}) {}

  // Returns whether the mouse click has selected something.
  // Used to prevent further propagation if necessary.
  onMouseClick(_position: {x: number, y: number}): boolean {
    return false;
  }

  onMouseOut(): void {}

  onFullRedraw(): void {}

  onDestroy(): void {}
}

type TrackAdapterClass<Config, Data> = {
  new (args: NewTrackArgs): TrackAdapter<Config, Data>
}

function hasNamespace(config: unknown): config is {
  namespace: string
} {
  return !!config && typeof config === 'object' && 'namespace' in config;
}

// Extend from this class instead of `TrackController` to use existing track
// controller implementations with `TrackWithControllerAdapter`.
export abstract class TrackControllerAdapter<Config, Data> {
  // This unique ID is just used to create the table names.
  // In the future we should probably use the track instance ID, but for now we
  // don't have access to it.
  private uuid = uuidv4();

  constructor(protected config: Config, protected engine: EngineProxy) {}

  protected async query(query: string) {
    const result = await this.engine.query(query);
    return result;
  }

  abstract onBoundsChange(start: time, end: time, resolution: duration):
      Promise<Data>;

  async onSetup(): Promise<void> {}
  async onDestroy(): Promise<void> {}

  // Returns a valid SQL table name with the given prefix that should be unique
  // for each track.
  tableName(prefix: string) {
    // Derive table name from, since that is unique for each track.
    // Track ID can be UUID but '-' is not valid for sql table name.
    const idSuffix = this.uuid.split('-').join('_');
    return `${prefix}_${idSuffix}`;
  }

  namespaceTable(tableName: string): string {
    if (hasNamespace(this.config)) {
      return this.config.namespace + '_' + tableName;
    } else {
      return tableName;
    }
  }
}

type TrackControllerAdapterClass<Config, Data> = {
  new (config: Config, engine: EngineProxy):
      TrackControllerAdapter<Config, Data>
}
