// 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 {assertFalse, assertTrue} from '../base/logging';
import {TimeSpan} from '../common/time';

const MAX_ZOOM_SPAN_SEC = 1e-8;  // 10 ns.

/**
 * Defines a mapping between number and seconds for the entire application.
 * Linearly scales time values from boundsMs to pixel values in boundsPx and
 * back.
 */
export class TimeScale {
  private timeBounds: TimeSpan;
  private _startPx: number;
  private _endPx: number;
  private secPerPx = 0;

  constructor(timeBounds: TimeSpan, boundsPx: [number, number]) {
    this.timeBounds = timeBounds;
    this._startPx = boundsPx[0];
    this._endPx = boundsPx[1];
    this.updateSlope();
  }

  private updateSlope() {
    this.secPerPx = this.timeBounds.duration / (this._endPx - this._startPx);
  }

  deltaTimeToPx(time: number): number {
    return Math.round(time / this.secPerPx);
  }

  timeToPx(time: number): number {
    return this._startPx + (time - this.timeBounds.start) / this.secPerPx;
  }

  pxToTime(px: number): number {
    return this.timeBounds.start + (px - this._startPx) * this.secPerPx;
  }

  deltaPxToDuration(px: number): number {
    return px * this.secPerPx;
  }

  setTimeBounds(timeBounds: TimeSpan) {
    this.timeBounds = timeBounds;
    this.updateSlope();
  }

  setLimitsPx(pxStart: number, pxEnd: number) {
    assertFalse(pxStart === pxEnd);
    assertTrue(pxStart >= 0 && pxEnd >= 0);
    this._startPx = pxStart;
    this._endPx = pxEnd;
    this.updateSlope();
  }

  timeInBounds(time: number): boolean {
    return this.timeBounds.isInBounds(time);
  }

  get startPx(): number {
    return this._startPx;
  }

  get endPx(): number {
    return this._endPx;
  }

  get widthPx(): number {
    return this._endPx - this._startPx;
  }

  get timeSpan(): TimeSpan {
    return this.timeBounds;
  }
}

export function computeZoom(
    scale: TimeScale, span: TimeSpan, zoomFactor: number, zoomPx: number):
    TimeSpan {
  const startPx = scale.startPx;
  const endPx = scale.endPx;
  const deltaPx = endPx - startPx;
  const deltaTime = span.end - span.start;
  const newDeltaTime = Math.max(deltaTime * zoomFactor, MAX_ZOOM_SPAN_SEC);
  const clampedZoomPx = Math.max(startPx, Math.min(endPx, zoomPx));
  const zoomTime = scale.pxToTime(clampedZoomPx);
  const r = (clampedZoomPx - startPx) / deltaPx;
  const newStartTime = zoomTime - newDeltaTime * r;
  const newEndTime = newStartTime + newDeltaTime;
  return new TimeSpan(newStartTime, newEndTime);
}
