// Copyright (C) 2023 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 {duration, Time, time} from '../base/time';
import {Actions} from '../common/actions';
import {cropText, drawIncompleteSlice} from '../common/canvas_utils';
import {getColorForSlice} from '../core/colorizer';
import {HighPrecisionTime} from '../common/high_precision_time';
import {TrackData} from '../common/track_data';
import {TimelineFetcher} from '../common/track_helper';
import {SliceRect, Track} from '../public';
import {getLegacySelection} from '../common/state';

import {CROP_INCOMPLETE_SLICE_FLAG} from './base_slice_track';
import {checkerboardExcept} from './checkerboard';
import {globals} from './globals';
import {PanelSize} from './panel';

export const SLICE_TRACK_KIND = 'ChromeSliceTrack';
const SLICE_HEIGHT = 18;
const TRACK_PADDING = 2;
const CHEVRON_WIDTH_PX = 10;
const HALF_CHEVRON_WIDTH_PX = CHEVRON_WIDTH_PX / 2;
const INCOMPLETE_SLICE_WIDTH_PX = 20;

export interface SliceData extends TrackData {
  // Slices are stored in a columnar fashion.
  strings: string[];
  sliceIds: Float64Array;
  starts: BigInt64Array;
  ends: BigInt64Array;
  depths: Uint16Array;
  titles: Uint16Array; // Index into strings.
  colors?: Uint16Array; // Index into strings.
  isInstant: Uint16Array;
  isIncomplete: Uint16Array;
  cpuTimeRatio?: Float64Array;
}

// Track base class which handles rendering slices in a generic way.
// This is the old way of rendering slices - i.e. "track v1" format  - and
// exists as a patch to allow old tracks to be converted to controller-less
// tracks before they are ported to v2.
// Slice tracks should extend this class and implement the abstract methods,
// notably onBoundsChange().
// Note: This class is deprecated and should not be used for new tracks. Use
// |BaseSliceTrack| instead.
export abstract class SliceTrackLEGACY implements Track {
  private fetcher = new TimelineFetcher(this.onBoundsChange.bind(this));

  constructor(
    private maxDepth: number,
    protected trackKey: string,
    private tableName: string,
    private namespace?: string,
  ) {}

  async onUpdate(): Promise<void> {
    await this.fetcher.requestDataForCurrentTime();
  }

  async onDestroy(): Promise<void> {
    this.fetcher.dispose();
  }

  abstract onBoundsChange(
    start: time,
    end: time,
    resolution: duration,
  ): Promise<SliceData>;

  protected namespaceTable(tableName: string = this.tableName): string {
    if (this.namespace) {
      return this.namespace + '_' + tableName;
    } else {
      return tableName;
    }
  }

  private hoveredTitleId = -1;

  // Font used to render the slice name on the current track.
  protected getFont() {
    return '12px Roboto Condensed';
  }

  render(ctx: CanvasRenderingContext2D, size: PanelSize): void {
    // TODO: fonts and colors should come from the CSS and not hardcoded here.
    const data = this.fetcher.data;
    if (data === undefined) return; // Can't possibly draw anything.

    const {visibleTimeSpan, visibleTimeScale} = globals.timeline;

    // If the cached trace slices don't fully cover the visible time range,
    // show a gray rectangle with a "Loading..." label.
    checkerboardExcept(
      ctx,
      this.getHeight(),
      0,
      size.width,
      visibleTimeScale.timeToPx(data.start),
      visibleTimeScale.timeToPx(data.end),
    );

    ctx.textAlign = 'center';

    // measuretext is expensive so we only use it once.
    const charWidth = ctx.measureText('ACBDLqsdfg').width / 10;

    // The draw of the rect on the selected slice must happen after the other
    // drawings, otherwise it would result under another rect.
    let drawRectOnSelected = () => {};

    for (let i = 0; i < data.starts.length; i++) {
      const tStart = Time.fromRaw(data.starts[i]);
      let tEnd = Time.fromRaw(data.ends[i]);
      const depth = data.depths[i];
      const titleId = data.titles[i];
      const sliceId = data.sliceIds[i];
      const isInstant = data.isInstant[i];
      const isIncomplete = data.isIncomplete[i];
      const title = data.strings[titleId];
      const colorOverride = data.colors && data.strings[data.colors[i]];
      if (isIncomplete) {
        // incomplete slice
        // TODO(stevegolton): This isn't exactly equivalent, ideally we should
        // choose tEnd once we've converted to screen space coords.
        tEnd = this.getEndTimeIfInComplete(tStart);
      }

      if (!visibleTimeSpan.intersects(tStart, tEnd)) {
        continue;
      }

      const pxEnd = size.width;
      const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
      const right = Math.min(visibleTimeScale.timeToPx(tEnd), pxEnd);

      const rect = {
        left,
        width: Math.max(right - left, 1),
        top: TRACK_PADDING + depth * SLICE_HEIGHT,
        height: SLICE_HEIGHT,
      };

      const currentSelection = getLegacySelection(globals.state);
      const isSelected =
        currentSelection &&
        currentSelection.kind === 'CHROME_SLICE' &&
        currentSelection.id !== undefined &&
        currentSelection.id === sliceId;

      const highlighted =
        titleId === this.hoveredTitleId ||
        globals.state.highlightedSliceId === sliceId;

      const hasFocus = highlighted || isSelected;
      const colorScheme = getColorForSlice(title);
      const colorObj = hasFocus ? colorScheme.variant : colorScheme.base;
      const textColor = hasFocus
        ? colorScheme.textVariant
        : colorScheme.textBase;

      let color: string;
      if (colorOverride === undefined) {
        color = colorObj.cssString;
      } else {
        color = colorOverride;
      }
      ctx.fillStyle = color;

      // We draw instant events as upward facing chevrons starting at A:
      //     A
      //    ###
      //   ##C##
      //  ##   ##
      // D       B
      // Then B, C, D and back to A:
      if (isInstant) {
        if (isSelected) {
          drawRectOnSelected = () => {
            ctx.save();
            ctx.translate(rect.left, rect.top);

            // Draw a rectangle around the selected slice
            ctx.strokeStyle = colorObj.setHSL({s: 100, l: 10}).cssString;
            ctx.beginPath();
            ctx.lineWidth = 3;
            ctx.strokeRect(
              -HALF_CHEVRON_WIDTH_PX,
              0,
              CHEVRON_WIDTH_PX,
              SLICE_HEIGHT,
            );
            ctx.closePath();

            // Draw inner chevron as interior
            ctx.fillStyle = color;
            this.drawChevron(ctx);

            ctx.restore();
          };
        } else {
          ctx.save();
          ctx.translate(rect.left, rect.top);
          this.drawChevron(ctx);
          ctx.restore();
        }
        continue;
      }

      if (isIncomplete && rect.width > SLICE_HEIGHT / 4) {
        drawIncompleteSlice(
          ctx,
          rect.left,
          rect.top,
          rect.width,
          SLICE_HEIGHT,
          !CROP_INCOMPLETE_SLICE_FLAG.get(),
        );
      } else if (
        data.cpuTimeRatio !== undefined &&
        data.cpuTimeRatio[i] < 1 - 1e-9
      ) {
        // We draw two rectangles, representing the ratio between wall time and
        // time spent on cpu.
        const cpuTimeRatio = data.cpuTimeRatio![i];
        const firstPartWidth = rect.width * cpuTimeRatio;
        const secondPartWidth = rect.width * (1 - cpuTimeRatio);
        ctx.fillRect(rect.left, rect.top, rect.width, SLICE_HEIGHT);
        ctx.fillStyle = '#FFFFFF50';
        ctx.fillRect(
          rect.left + firstPartWidth,
          rect.top,
          secondPartWidth,
          SLICE_HEIGHT,
        );
      } else {
        ctx.fillRect(rect.left, rect.top, rect.width, SLICE_HEIGHT);
      }

      // Selected case
      if (isSelected) {
        drawRectOnSelected = () => {
          ctx.strokeStyle = colorObj.setHSL({s: 100, l: 10}).cssString;
          ctx.beginPath();
          ctx.lineWidth = 3;
          ctx.strokeRect(
            rect.left,
            rect.top - 1.5,
            rect.width,
            SLICE_HEIGHT + 3,
          );
          ctx.closePath();
        };
      }

      // Don't render text when we have less than 5px to play with.
      if (rect.width >= 5) {
        ctx.fillStyle = textColor.cssString;
        const displayText = cropText(title, charWidth, rect.width);
        const rectXCenter = rect.left + rect.width / 2;
        ctx.textBaseline = 'middle';
        ctx.font = this.getFont();
        ctx.fillText(displayText, rectXCenter, rect.top + SLICE_HEIGHT / 2);
      }
    }
    drawRectOnSelected();
  }

  drawChevron(ctx: CanvasRenderingContext2D) {
    // Draw a chevron at a fixed location and size. Should be used with
    // ctx.translate and ctx.scale to alter location and size.
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
    ctx.lineTo(0, SLICE_HEIGHT - HALF_CHEVRON_WIDTH_PX);
    ctx.lineTo(-HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
    ctx.lineTo(0, 0);
    ctx.fill();
  }

  getSliceIndex({x, y}: {x: number; y: number}): number | void {
    const data = this.fetcher.data;
    if (data === undefined) return;
    const {visibleTimeScale: timeScale} = globals.timeline;
    if (y < TRACK_PADDING) return;
    const instantWidthTime = timeScale.pxDeltaToDuration(HALF_CHEVRON_WIDTH_PX);
    const t = timeScale.pxToHpTime(x);
    const depth = Math.floor((y - TRACK_PADDING) / SLICE_HEIGHT);

    for (let i = 0; i < data.starts.length; i++) {
      if (depth !== data.depths[i]) {
        continue;
      }
      const start = Time.fromRaw(data.starts[i]);
      const tStart = HighPrecisionTime.fromTime(start);
      if (data.isInstant[i]) {
        if (tStart.sub(t).abs().lt(instantWidthTime)) {
          return i;
        }
      } else {
        const end = Time.fromRaw(data.ends[i]);
        let tEnd = HighPrecisionTime.fromTime(end);
        if (data.isIncomplete[i]) {
          const endTime = this.getEndTimeIfInComplete(start);
          tEnd = HighPrecisionTime.fromTime(endTime);
        }
        if (tStart.lte(t) && t.lte(tEnd)) {
          return i;
        }
      }
    }
  }

  getEndTimeIfInComplete(start: time): time {
    const {visibleTimeScale, visibleWindowTime} = globals.timeline;

    let end = visibleWindowTime.end.toTime('ceil');
    if (CROP_INCOMPLETE_SLICE_FLAG.get()) {
      const widthTime = visibleTimeScale
        .pxDeltaToDuration(INCOMPLETE_SLICE_WIDTH_PX)
        .toTime();
      end = Time.add(start, widthTime);
    }

    return end;
  }

  onMouseMove({x, y}: {x: number; y: number}) {
    this.hoveredTitleId = -1;
    globals.dispatch(Actions.setHighlightedSliceId({sliceId: -1}));
    const sliceIndex = this.getSliceIndex({x, y});
    if (sliceIndex === undefined) return;
    const data = this.fetcher.data;
    if (data === undefined) return;
    this.hoveredTitleId = data.titles[sliceIndex];
    const sliceId = data.sliceIds[sliceIndex];
    globals.dispatch(Actions.setHighlightedSliceId({sliceId}));
  }

  onMouseOut() {
    this.hoveredTitleId = -1;
    globals.dispatch(Actions.setHighlightedSliceId({sliceId: -1}));
  }

  onMouseClick({x, y}: {x: number; y: number}): boolean {
    const sliceIndex = this.getSliceIndex({x, y});
    if (sliceIndex === undefined) return false;
    const data = this.fetcher.data;
    if (data === undefined) return false;
    const sliceId = data.sliceIds[sliceIndex];
    if (sliceId !== undefined && sliceId !== -1) {
      globals.setLegacySelection(
        {
          kind: 'CHROME_SLICE',
          id: sliceId,
          trackKey: this.trackKey,
          table: this.namespace,
        },
        {
          clearSearch: true,
          pendingScrollId: undefined,
          switchToCurrentSelectionTab: true,
        },
      );
      return true;
    }
    return false;
  }

  getHeight() {
    return SLICE_HEIGHT * (this.maxDepth + 1) + 2 * TRACK_PADDING;
  }

  getSliceRect(tStart: time, tEnd: time, depth: number): SliceRect | undefined {
    const {windowSpan, visibleTimeScale, visibleTimeSpan} = globals.timeline;

    const pxEnd = windowSpan.end;
    const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
    const right = Math.min(visibleTimeScale.timeToPx(tEnd), pxEnd);

    const visible = visibleTimeSpan.intersects(tStart, tEnd);

    return {
      left,
      width: Math.max(right - left, 1),
      top: TRACK_PADDING + depth * SLICE_HEIGHT,
      height: SLICE_HEIGHT,
      visible,
    };
  }
}
