// 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 {assertTrue} from '../base/logging';
import {duration, Span, Time, time, TimeSpan} from '../base/time';
import {Actions} from '../common/actions';
import {
  HighPrecisionTime,
  HighPrecisionTimeSpan,
} from '../common/high_precision_time';
import {
  Area,
  FrontendLocalState as FrontendState,
  Timestamped,
  VisibleState,
} from '../common/state';
import {raf} from '../core/raf_scheduler';

import {globals} from './globals';
import {ratelimit} from './rate_limiters';
import {PxSpan, TimeScale} from './time_scale';

interface Range {
  start?: number;
  end?: number;
}

function chooseLatest<T extends Timestamped>(current: T, next: T): T {
  if (next !== current && next.lastUpdate > current.lastUpdate) {
    // |next| is from state. Callers may mutate the return value of
    // this function so we need to clone |next| to prevent bad mutations
    // of state:
    return Object.assign({}, next);
  }
  return current;
}

// Immutable object describing a (high precision) time window, providing methods
// for common mutation operations (pan, zoom), and accessors for common
// properties such as spans and durations in several formats.
// This object relies on the trace time span in globals and ensures start and
// ends of the time window remain within the confines of the trace time, and
// also applies a hard-coded minimum zoom level.
export class TimeWindow {
  readonly hpTimeSpan = HighPrecisionTimeSpan.ZERO;
  readonly timeSpan = TimeSpan.ZERO;

  private readonly MIN_DURATION_NS = 10;

  constructor(start = HighPrecisionTime.ZERO, durationNanos = 1e9) {
    durationNanos = Math.max(this.MIN_DURATION_NS, durationNanos);

    const traceTimeSpan = globals.stateTraceTime();
    const traceDurationNanos = traceTimeSpan.duration.nanos;

    if (durationNanos > traceDurationNanos) {
      start = traceTimeSpan.start;
      durationNanos = traceDurationNanos;
    }

    if (start.lt(traceTimeSpan.start)) {
      start = traceTimeSpan.start;
    }

    const end = start.addNanos(durationNanos);
    if (end.gt(traceTimeSpan.end)) {
      start = traceTimeSpan.end.subNanos(durationNanos);
    }

    this.hpTimeSpan =
        new HighPrecisionTimeSpan(start, start.addNanos(durationNanos));
    this.timeSpan = new TimeSpan(
      this.hpTimeSpan.start.toTime('floor'),
      this.hpTimeSpan.end.toTime('ceil'));
  }

  static fromHighPrecisionTimeSpan(span: Span<HighPrecisionTime>): TimeWindow {
    return new TimeWindow(span.start, span.duration.nanos);
  }

  // Pan the window by certain number of seconds
  pan(offset: HighPrecisionTime) {
    return new TimeWindow(
      this.hpTimeSpan.start.add(offset), this.hpTimeSpan.duration.nanos);
  }

  // Zoom in or out a bit centered on a specific offset from the root
  // Offset represents the center of the zoom as a normalized value between 0
  // and 1 where 0 is the start of the time window and 1 is the end
  zoom(ratio: number, offset: number) {
    const traceDuration = globals.stateTraceTime().duration;
    const minDuration = Math.min(this.MIN_DURATION_NS, traceDuration.nanos);
    const currentDurationNanos = this.hpTimeSpan.duration.nanos;
    const newDurationNanos =
        Math.max(currentDurationNanos * ratio, minDuration);
    // Delta between new and old duration
    // +ve if new duration is shorter than old duration
    const durationDeltaNanos = currentDurationNanos - newDurationNanos;
    // If offset is 0, don't move the start at all
    // If offset if 1, move the start by the amount the duration has changed
    // If new duration is shorter - move start to right
    // If new duration is longer - move start to left
    const start = this.hpTimeSpan.start.addNanos(durationDeltaNanos * offset);
    const durationNanos = newDurationNanos;
    return new TimeWindow(start, durationNanos);
  }

  createTimeScale(startPx: number, endPx: number): TimeScale {
    return new TimeScale(
      this.hpTimeSpan.start,
      this.hpTimeSpan.duration.nanos,
      new PxSpan(startPx, endPx));
  }

  get earliest(): time {
    return this.timeSpan.start;
  }

  get latest(): time {
    return this.timeSpan.end;
  }
}

/**
 * State that is shared between several frontend components, but not the
 * controller. This state is updated at 60fps.
 */
export class Timeline {
  private visibleWindow = new TimeWindow();
  private _timeScale = this.visibleWindow.createTimeScale(0, 0);
  private _windowSpan = PxSpan.ZERO;

  // This is used to calculate the tracks within a Y range for area selection.
  areaY: Range = {};

  private _visibleState: VisibleState = {
    lastUpdate: 0,
    start: Time.ZERO,
    end: Time.fromSeconds(10),
    resolution: 1n,
  };

  private _selectedArea?: Area;

  // TODO: there is some redundancy in the fact that both |visibleWindowTime|
  // and a |timeScale| have a notion of time range. That should live in one
  // place only.

  zoomVisibleWindow(ratio: number, centerPoint: number) {
    this.visibleWindow = this.visibleWindow.zoom(ratio, centerPoint);
    this._timeScale = this.visibleWindow.createTimeScale(
      this._windowSpan.start, this._windowSpan.end);
    this.kickUpdateLocalState();
  }

  panVisibleWindow(delta: HighPrecisionTime) {
    this.visibleWindow = this.visibleWindow.pan(delta);
    this._timeScale = this.visibleWindow.createTimeScale(
      this._windowSpan.start, this._windowSpan.end);
    this.kickUpdateLocalState();
  }

  mergeState(state: FrontendState): void {
    // This is unfortunately subtle. This class mutates this._visibleState.
    // Since we may not mutate |state| (in order to make immer's immutable
    // updates work) this means that we have to make a copy of the visibleState.
    // when updating it. We don't want to have to do that unnecessarily so
    // chooseLatest returns a shallow clone of state.visibleState *only* when
    // that is the newer state. All of these complications should vanish when
    // we remove this class.
    const previousVisibleState = this._visibleState;
    this._visibleState = chooseLatest(this._visibleState, state.visibleState);
    const visibleStateWasUpdated = previousVisibleState !== this._visibleState;
    if (visibleStateWasUpdated) {
      this.updateLocalTime(new HighPrecisionTimeSpan(
        HighPrecisionTime.fromTime(this._visibleState.start),
        HighPrecisionTime.fromTime(this._visibleState.end),
      ));
    }
  }

  // Set the highlight box to draw
  selectArea(
    start: time, end: time,
    tracks = this._selectedArea ? this._selectedArea.tracks : []) {
    assertTrue(
      end >= start,
      `Impossible select area: start [${start}] >= end [${end}]`);
    this._selectedArea = {start, end, tracks};
    raf.scheduleFullRedraw();
  }

  deselectArea() {
    this._selectedArea = undefined;
    raf.scheduleRedraw();
  }

  get selectedArea(): Area|undefined {
    return this._selectedArea;
  }

  private ratelimitedUpdateVisible = ratelimit(() => {
    globals.dispatch(Actions.setVisibleTraceTime(this._visibleState));
  }, 50);

  private updateLocalTime(ts: Span<HighPrecisionTime>) {
    const traceBounds = globals.stateTraceTime();
    const start = ts.start.clamp(traceBounds.start, traceBounds.end);
    const end = ts.end.clamp(traceBounds.start, traceBounds.end);
    this.visibleWindow = TimeWindow.fromHighPrecisionTimeSpan(
      new HighPrecisionTimeSpan(start, end));
    this._timeScale = this.visibleWindow.createTimeScale(
      this._windowSpan.start, this._windowSpan.end);
    this.updateResolution();
  }

  private updateResolution() {
    this._visibleState.lastUpdate = Date.now() / 1000;
    this._visibleState.resolution = globals.getCurResolution();
    this.ratelimitedUpdateVisible();
  }

  private kickUpdateLocalState() {
    this._visibleState.lastUpdate = Date.now() / 1000;
    this._visibleState.start = this.visibleWindowTime.start.toTime();
    this._visibleState.end = this.visibleWindowTime.end.toTime();
    this._visibleState.resolution = globals.getCurResolution();
    this.ratelimitedUpdateVisible();
  }

  updateVisibleTime(ts: Span<HighPrecisionTime>) {
    this.updateLocalTime(ts);
    this.kickUpdateLocalState();
  }

  // Whenever start/end px of the timeScale is changed, update
  // the resolution.
  updateLocalLimits(pxStart: number, pxEnd: number) {
    // Numbers received here can be negative or equal, but we should fix that
    // before updating the timescale.
    pxStart = Math.max(0, pxStart);
    pxEnd = Math.max(0, pxEnd);
    if (pxStart === pxEnd) pxEnd = pxStart + 1;
    this._timeScale = this.visibleWindow.createTimeScale(pxStart, pxEnd);
    this._windowSpan = new PxSpan(pxStart, pxEnd);
    this.updateResolution();
  }

  // Get the time scale for the visible window
  get visibleTimeScale(): TimeScale {
    return this._timeScale;
  }

  // Produces a TimeScale object for this time window provided start and end px
  getTimeScale(startPx: number, endPx: number): TimeScale {
    return this.visibleWindow.createTimeScale(startPx, endPx);
  }

  // Get the bounds of the window in pixels
  get windowSpan(): PxSpan {
    return this._windowSpan;
  }

  // Get the bounds of the visible window as a high-precision time span
  get visibleWindowTime(): Span<HighPrecisionTime> {
    return this.visibleWindow.hpTimeSpan;
  }

  // Get the bounds of the visible window as a time span
  get visibleTimeSpan(): Span<time, duration> {
    return this.visibleWindow.timeSpan;
  }
}
