// 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 {Engine} from '../common/engine';
import {TrackState} from '../common/state';
import {TrackData} from '../common/track_data';

import {checkerboard} from './checkerboard';
import {globals} from './globals';
import {TrackButtonAttrs} from './track_panel';

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

// 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: Engine;

  // 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, timeScale} = globals.frontendLocalState;
      const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
      const endPx = Math.ceil(timeScale.timeToPx(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.timeScale.endPx;
    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(_tStart: number, _tEnd: number, _depth: number): SliceRect
      |undefined {
    return undefined;
  }
}
