// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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 {BigintMath} from '../base/bigint_math';
import {formatDuration, Span, Timecode, toDomainTime} from '../common/time';
import {
  TPTime,
  TPTimeSpan,
} from '../common/time';

import {
  BACKGROUND_COLOR,
  FOREGROUND_COLOR,
  TRACK_SHELL_WIDTH,
} from './css_constants';
import {globals} from './globals';
import {
  getMaxMajorTicks,
  TickGenerator,
  TickType,
  timeScaleForVisibleWindow,
} from './gridline_helper';
import {Panel, PanelSize} from './panel';

export interface BBox {
  x: number;
  y: number;
  width: number;
  height: number;
}

// Draws a vertical line with two horizontal tails at the left and right and
// a label in the middle. It looks a bit like a stretched H:
// |--- Label ---|
// The |target| bounding box determines where to draw the H.
// The |bounds| bounding box gives the visible region, this is used to adjust
// the positioning of the label to ensure it is on screen.
function drawHBar(
    ctx: CanvasRenderingContext2D, target: BBox, bounds: BBox, label: string) {
  ctx.fillStyle = FOREGROUND_COLOR;

  const xLeft = Math.floor(target.x);
  const xRight = Math.floor(target.x + target.width);
  const yMid = Math.floor(target.height / 2 + target.y);
  const xWidth = xRight - xLeft;

  // Don't draw in the track shell.
  ctx.beginPath();
  ctx.rect(bounds.x, bounds.y, bounds.width, bounds.height);
  ctx.clip();

  // Draw horizontal bar of the H.
  ctx.fillRect(xLeft, yMid, xWidth, 1);
  // Draw left vertical bar of the H.
  ctx.fillRect(xLeft, target.y, 1, target.height);
  // Draw right vertical bar of the H.
  ctx.fillRect(xRight, target.y, 1, target.height);

  const labelWidth = ctx.measureText(label).width;

  // Find a good position for the label:
  // By default put the label in the middle of the H:
  let labelXLeft = Math.floor(xWidth / 2 - labelWidth / 2 + xLeft);

  if (labelWidth > target.width || labelXLeft < bounds.x ||
      (labelXLeft + labelWidth) > (bounds.x + bounds.width)) {
    // It won't fit in the middle or would be at least partly out of bounds
    // so put it either to the left or right:
    if (xRight > bounds.x + bounds.width) {
      // If the H extends off the right side of the screen the label
      // goes on the left of the H.
      labelXLeft = xLeft - labelWidth - 3;
    } else {
      // Otherwise the label goes on the right of the H.
      labelXLeft = xRight + 3;
    }
  }

  ctx.fillStyle = BACKGROUND_COLOR;
  ctx.fillRect(labelXLeft - 1, 0, labelWidth + 1, target.height);

  ctx.textBaseline = 'middle';
  ctx.fillStyle = FOREGROUND_COLOR;
  ctx.font = '10px Roboto Condensed';
  ctx.fillText(label, labelXLeft, yMid);
}

function drawIBar(
    ctx: CanvasRenderingContext2D, xPos: number, bounds: BBox, label: string) {
  if (xPos < bounds.x) return;

  ctx.fillStyle = FOREGROUND_COLOR;
  ctx.fillRect(xPos, 0, 1, bounds.width);

  const yMid = Math.floor(bounds.height / 2 + bounds.y);
  const labelWidth = ctx.measureText(label).width;
  const padding = 3;

  let xPosLabel;
  if (xPos + padding + labelWidth > bounds.width) {
    xPosLabel = xPos - padding;
    ctx.textAlign = 'right';
  } else {
    xPosLabel = xPos + padding;
    ctx.textAlign = 'left';
  }

  ctx.fillStyle = BACKGROUND_COLOR;
  ctx.fillRect(xPosLabel - 1, 0, labelWidth + 2, bounds.height);

  ctx.textBaseline = 'middle';
  ctx.fillStyle = FOREGROUND_COLOR;
  ctx.font = '10px Roboto Condensed';
  ctx.fillText(label, xPosLabel, yMid);
}

export class TimeSelectionPanel extends Panel {
  view() {
    return m('.time-selection-panel');
  }

  renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
    ctx.fillStyle = '#999';
    ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);

    ctx.save();
    ctx.beginPath();
    ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
    ctx.clip();

    const span = globals.frontendLocalState.visibleWindow.timestampSpan;
    if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
      const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
      const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
      for (const {type, time} of new TickGenerator(
               span, maxMajorTicks, globals.state.traceTime.start)) {
        const px = Math.floor(map.tpTimeToPx(time));
        if (type === TickType.MAJOR) {
          ctx.fillRect(px, 0, 1, size.height);
        }
      }
    }

    const localArea = globals.frontendLocalState.selectedArea;
    const selection = globals.state.currentSelection;
    if (localArea !== undefined) {
      const start = BigintMath.min(localArea.start, localArea.end);
      const end = BigintMath.max(localArea.start, localArea.end);
      this.renderSpan(ctx, size, new TPTimeSpan(start, end));
    } else if (selection !== null && selection.kind === 'AREA') {
      const selectedArea = globals.state.areas[selection.areaId];
      const start = BigintMath.min(selectedArea.start, selectedArea.end);
      const end = BigintMath.max(selectedArea.start, selectedArea.end);
      this.renderSpan(ctx, size, new TPTimeSpan(start, end));
    }

    if (globals.state.hoverCursorTimestamp !== -1n) {
      this.renderHover(ctx, size, globals.state.hoverCursorTimestamp);
    }

    for (const note of Object.values(globals.state.notes)) {
      const noteIsSelected = selection !== null && selection.kind === 'AREA' &&
          selection.noteId === note.id;
      if (note.noteType === 'AREA' && !noteIsSelected) {
        const selectedArea = globals.state.areas[note.areaId];
        this.renderSpan(
            ctx, size, new TPTimeSpan(selectedArea.start, selectedArea.end));
      }
    }

    ctx.restore();
  }

  renderHover(ctx: CanvasRenderingContext2D, size: PanelSize, ts: TPTime) {
    const {visibleTimeScale} = globals.frontendLocalState;
    const xPos =
        TRACK_SHELL_WIDTH + Math.floor(visibleTimeScale.tpTimeToPx(ts));
    const domainTime = toDomainTime(ts);
    const label = new Timecode(domainTime).dhhmmss;
    drawIBar(ctx, xPos, this.bounds(size), label);
  }

  renderSpan(
      ctx: CanvasRenderingContext2D, size: PanelSize, span: Span<TPTime>) {
    const {visibleTimeScale} = globals.frontendLocalState;
    const xLeft = visibleTimeScale.tpTimeToPx(span.start);
    const xRight = visibleTimeScale.tpTimeToPx(span.end);
    const label = formatDuration(span.duration);
    drawHBar(
        ctx,
        {
          x: TRACK_SHELL_WIDTH + xLeft,
          y: 0,
          width: xRight - xLeft,
          height: size.height,
        },
        this.bounds(size),
        label);
  }

  private bounds(size: PanelSize): BBox {
    return {
      x: TRACK_SHELL_WIDTH,
      y: 0,
      width: size.width - TRACK_SHELL_WIDTH,
      height: size.height,
    };
  }
}
