// Copyright (C) 2018 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 {assertExists} from '../base/logging';
import {EngineProxy} from '../common/engine';
import {HighPrecisionTimeSpan} from '../common/high_precision_time';
import {TrackState} from '../common/state';
import {TPTime} from '../common/time';
import {TrackData} from '../common/track_data';

import {checkerboard} from './checkerboard';
import {globals} from './globals';
import {PxSpan, TimeScale} from './time_scale';
import {TrackButtonAttrs} from './track_panel';

// Args passed to the track constructors when creating a new track.
export interface NewTrackArgs {
  trackId: string;
  engine: EngineProxy;
}

// This interface forces track implementations to have some static properties.
// Typescript does not have abstract static members, which is why this needs to
// be in a separate interface.
export interface TrackCreator {
  // Store the kind explicitly as a string as opposed to using class.kind in
  // case we ever minify our code.
  readonly kind: string;

  // We need the |create| method because the stored value in the registry can be
  // an abstract class, and we cannot call 'new' on an abstract class.
  create(args: NewTrackArgs): Track;
}

export interface SliceRect {
  left: number;
  width: number;
  top: number;
  height: number;
  visible: boolean;
}

// The abstract class that needs to be implemented by all tracks.
export abstract class Track<Config = {}, Data extends TrackData = TrackData> {
  // The UI-generated track ID (not to be confused with the SQL track.id).
  protected readonly trackId: string;
  protected readonly engine: EngineProxy;

  // When true this is a new controller-less track type.
  // TODO(hjd): eventually all tracks will be controller-less and this
  // should be removed then.
  protected frontendOnly = false;

  // Caches the last state.track[this.trackId]. This is to deal with track
  // deletion, see comments in trackState() below.
  private lastTrackState: TrackState;

  constructor(args: NewTrackArgs) {
    this.trackId = args.trackId;
    this.engine = args.engine;
    this.lastTrackState = assertExists(globals.state.tracks[this.trackId]);
  }

  // Last call the track will receive. Called just before the last reference to
  // this object is removed.
  onDestroy() {}

  protected abstract renderCanvas(ctx: CanvasRenderingContext2D): void;

  protected get trackState(): TrackState {
    // We can end up in a state where a Track is still in the mithril renderer
    // tree but its corresponding state has been deleted. This can happen in the
    // interval of time between a track being removed from the state and the
    // next animation frame that would remove the Track object. If a mouse event
    // is dispatched in the meanwhile (or a promise is resolved), we need to be
    // able to access the state. Hence the caching logic here.
    const trackState = globals.state.tracks[this.trackId];
    if (trackState === undefined) {
      return this.lastTrackState;
    }
    this.lastTrackState = trackState;
    return trackState;
  }

  get config(): Config {
    return this.trackState.config as Config;
  }

  data(): Data|undefined {
    if (this.frontendOnly) {
      return undefined;
    }
    return globals.trackDataStore.get(this.trackId) as Data;
  }

  getHeight(): number {
    return 40;
  }

  getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
    return [];
  }

  getContextMenu(): m.Vnode<any>|null {
    return null;
  }

  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 {}

  render(ctx: CanvasRenderingContext2D) {
    globals.frontendLocalState.addVisibleTrack(this.trackState.id);
    if (this.data() === undefined && !this.frontendOnly) {
      const {visibleWindowTime, visibleTimeScale} = globals.frontendLocalState;
      const startPx =
          Math.floor(visibleTimeScale.hpTimeToPx(visibleWindowTime.start));
      const endPx =
          Math.ceil(visibleTimeScale.hpTimeToPx(visibleWindowTime.end));
      checkerboard(ctx, this.getHeight(), startPx, endPx);
    } else {
      this.renderCanvas(ctx);
    }
  }

  drawTrackHoverTooltip(
      ctx: CanvasRenderingContext2D, pos: {x: number, y: number}, text: string,
      text2?: string) {
    ctx.font = '10px Roboto Condensed';
    ctx.textBaseline = 'middle';
    ctx.textAlign = 'left';

    // TODO(hjd): Avoid measuring text all the time (just use monospace?)
    const textMetrics = ctx.measureText(text);
    const text2Metrics = ctx.measureText(text2 || '');

    // Padding on each side of the box containing the tooltip:
    const paddingPx = 4;

    // Figure out the width of the tool tip box:
    let width = Math.max(textMetrics.width, text2Metrics.width);
    width += paddingPx * 2;

    // and the height:
    let height = 0;
    height += textMetrics.fontBoundingBoxAscent;
    height += textMetrics.fontBoundingBoxDescent;
    if (text2 !== undefined) {
      height += text2Metrics.fontBoundingBoxAscent;
      height += text2Metrics.fontBoundingBoxDescent;
    }
    height += paddingPx * 2;

    let x = pos.x;
    let y = pos.y;

    // Move box to the top right of the mouse:
    x += 10;
    y -= 10;

    // Ensure the box is on screen:
    const endPx = globals.frontendLocalState.visibleTimeScale.pxSpan.end;
    if (x + width > endPx) {
      x -= x + width - endPx;
    }
    if (y < 0) {
      y = 0;
    }
    if (y + height > this.getHeight()) {
      y -= y + height - this.getHeight();
    }

    // Draw everything:
    ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
    ctx.fillRect(x, y, width, height);

    ctx.fillStyle = 'hsl(200, 50%, 40%)';
    ctx.fillText(
        text, x + paddingPx, y + paddingPx + textMetrics.fontBoundingBoxAscent);
    if (text2 !== undefined) {
      const yOffsetPx = textMetrics.fontBoundingBoxAscent +
          textMetrics.fontBoundingBoxDescent +
          text2Metrics.fontBoundingBoxAscent;
      ctx.fillText(text2, x + paddingPx, y + paddingPx + yOffsetPx);
    }
  }

  // Returns a place where a given slice should be drawn. Should be implemented
  // only for track types that support slices e.g. chrome_slice, async_slices
  // tStart - slice start time in seconds, tEnd - slice end time in seconds,
  // depth - slice depth
  getSliceRect(
      _visibleTimeScale: TimeScale, _visibleWindowTime: HighPrecisionTimeSpan,
      _windowSpan: PxSpan, _tStart: TPTime, _tEnd: TPTime,
      _depth: number): SliceRect|undefined {
    return undefined;
  }
}
