// Copyright (C) 2018 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 {Time, time, toISODateOnly} from '../base/time';
import {timestampFormat} from '../core/timestamp_format';
import {TRACK_SHELL_WIDTH} from './css_constants';
import {
  getMaxMajorTicks,
  MIN_PX_PER_STEP,
  generateTicks,
  TickType,
} from './gridline_helper';
import {Size2D} from '../base/geom';
import {Panel} from './panel_container';
import {TimeScale} from '../base/time_scale';
import {canvasClip} from '../base/canvas_utils';
import {Trace} from '../public/trace';
import {assertUnreachable} from '../base/logging';
import {TimestampFormat} from '../public/timeline';

export class TimeAxisPanel implements Panel {
  readonly kind = 'panel';
  readonly selectable = false;
  readonly id = 'time-axis-panel';

  constructor(private readonly trace: Trace) {}

  render(): m.Children {
    return m('.time-axis-panel');
  }

  renderCanvas(ctx: CanvasRenderingContext2D, size: Size2D) {
    ctx.fillStyle = '#999';
    ctx.textAlign = 'left';
    ctx.font = '11px Roboto Condensed';

    this.renderOffsetTimestamp(ctx);

    const trackSize = {...size, width: size.width - TRACK_SHELL_WIDTH};
    ctx.save();
    ctx.translate(TRACK_SHELL_WIDTH, 0);
    canvasClip(ctx, 0, 0, trackSize.width, trackSize.height);
    this.renderPanel(ctx, trackSize);
    ctx.restore();

    ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
  }

  private renderOffsetTimestamp(ctx: CanvasRenderingContext2D): void {
    const offset = this.trace.timeline.timestampOffset();
    const timestampFormat = this.trace.timeline.timestampFormat;
    switch (timestampFormat) {
      case TimestampFormat.TraceNs:
      case TimestampFormat.TraceNsLocale:
        break;
      case TimestampFormat.Seconds:
      case TimestampFormat.Milliseconds:
      case TimestampFormat.Microseconds:
      case TimestampFormat.Timecode:
        const width = renderTimestamp(ctx, offset, 6, 10, MIN_PX_PER_STEP);
        ctx.fillText('+', 6 + width + 2, 10, 6);
        break;
      case TimestampFormat.UTC:
        const offsetDate = Time.toDate(
          this.trace.traceInfo.utcOffset,
          this.trace.traceInfo.realtimeOffset,
        );
        const dateStr = toISODateOnly(offsetDate);
        ctx.fillText(`UTC ${dateStr}`, 6, 10);
        break;
      case TimestampFormat.TraceTz:
        const offsetTzDate = Time.toDate(
          this.trace.traceInfo.traceTzOffset,
          this.trace.traceInfo.realtimeOffset,
        );
        const dateTzStr = toISODateOnly(offsetTzDate);
        ctx.fillText(dateTzStr, 6, 10);
        break;
      default:
        assertUnreachable(timestampFormat);
    }
  }

  private renderPanel(ctx: CanvasRenderingContext2D, size: Size2D): void {
    const visibleWindow = this.trace.timeline.visibleWindow;
    const timescale = new TimeScale(visibleWindow, {
      left: 0,
      right: size.width,
    });
    const timespan = visibleWindow.toTimeSpan();
    const offset = this.trace.timeline.timestampOffset();

    // Draw time axis.
    if (size.width > 0 && timespan.duration > 0n) {
      const maxMajorTicks = getMaxMajorTicks(size.width);
      const tickGen = generateTicks(timespan, maxMajorTicks, offset);
      for (const {type, time} of tickGen) {
        if (type === TickType.MAJOR) {
          const position = Math.floor(timescale.timeToPx(time));
          ctx.fillRect(position, 0, 1, size.height);
          const domainTime = this.trace.timeline.toDomainTime(time);
          renderTimestamp(ctx, domainTime, position + 5, 10, MIN_PX_PER_STEP);
        }
      }
    }
  }
}

function renderTimestamp(
  ctx: CanvasRenderingContext2D,
  time: time,
  x: number,
  y: number,
  minWidth: number,
) {
  const fmt = timestampFormat();
  switch (fmt) {
    case TimestampFormat.UTC:
    case TimestampFormat.TraceTz:
    case TimestampFormat.Timecode:
      return renderTimecode(ctx, time, x, y, minWidth);
    case TimestampFormat.TraceNs:
      return renderRawTimestamp(ctx, time.toString(), x, y, minWidth);
    case TimestampFormat.TraceNsLocale:
      return renderRawTimestamp(ctx, time.toLocaleString(), x, y, minWidth);
    case TimestampFormat.Seconds:
      return renderRawTimestamp(ctx, Time.formatSeconds(time), x, y, minWidth);
    case TimestampFormat.Milliseconds:
      return renderRawTimestamp(
        ctx,
        Time.formatMilliseconds(time),
        x,
        y,
        minWidth,
      );
    case TimestampFormat.Microseconds:
      return renderRawTimestamp(
        ctx,
        Time.formatMicroseconds(time),
        x,
        y,
        minWidth,
      );
    default:
      const z: never = fmt;
      throw new Error(`Invalid timestamp ${z}`);
  }
}

// Print a time on the canvas in raw format.
function renderRawTimestamp(
  ctx: CanvasRenderingContext2D,
  time: string,
  x: number,
  y: number,
  minWidth: number,
) {
  ctx.font = '11px Roboto Condensed';
  ctx.fillText(time, x, y, minWidth);
  return ctx.measureText(time).width;
}

// Print a timecode over 2 lines with this formatting:
// DdHH:MM:SS
// mmm uuu nnn
// Returns the resultant width of the timecode.
function renderTimecode(
  ctx: CanvasRenderingContext2D,
  time: time,
  x: number,
  y: number,
  minWidth: number,
): number {
  const timecode = Time.toTimecode(time);
  ctx.font = '11px Roboto Condensed';

  const {dhhmmss} = timecode;
  const thinSpace = '\u2009';
  const subsec = timecode.subsec(thinSpace);
  ctx.fillText(dhhmmss, x, y, minWidth);
  const {width: firstRowWidth} = ctx.measureText(subsec);

  ctx.font = '10.5px Roboto Condensed';
  ctx.fillText(subsec, x, y + 10, minWidth);
  const {width: secondRowWidth} = ctx.measureText(subsec);

  return Math.max(firstRowWidth, secondRowWidth);
}
