// Copyright (C) 2020 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 {time} from '../base/time';
import {exists} from '../base/utils';
import {TrackState} from '../common/state';
import {SliceRect} from '../public';

import {TRACK_SHELL_WIDTH} from './css_constants';
import {ALL_CATEGORIES, getFlowCategories} from './flow_events_panel';
import {Flow, FlowPoint, globals} from './globals';
import {Panel} from './panel_container';

const TRACK_GROUP_CONNECTION_OFFSET = 5;
const TRIANGLE_SIZE = 5;
const CIRCLE_RADIUS = 3;
const BEZIER_OFFSET = 30;

const CONNECTED_FLOW_HUE = 10;
const SELECTED_FLOW_HUE = 230;

const DEFAULT_FLOW_WIDTH = 2;
const FOCUSED_FLOW_WIDTH = 3;

const HIGHLIGHTED_FLOW_INTENSITY = 45;
const FOCUSED_FLOW_INTENSITY = 55;
const DEFAULT_FLOW_INTENSITY = 70;

type LineDirection = 'LEFT' | 'RIGHT' | 'UP' | 'DOWN';
type ConnectionType = 'TRACK' | 'TRACK_GROUP';

interface TrackPanelInfo {
  panel: Panel;
  yStart: number;
}

interface TrackGroupPanelInfo {
  panel: Panel;
  yStart: number;
  height: number;
}

function getTrackIds(track: TrackState): number[] {
  const trackDesc = globals.trackManager.resolveTrackInfo(track.uri);
  return trackDesc?.trackIds ?? [];
}

export class FlowEventsRendererArgs {
  trackIdToTrackPanel: Map<number, TrackPanelInfo>;
  groupIdToTrackGroupPanel: Map<string, TrackGroupPanelInfo>;

  constructor(public canvasWidth: number, public canvasHeight: number) {
    this.trackIdToTrackPanel = new Map<number, TrackPanelInfo>();
    this.groupIdToTrackGroupPanel = new Map<string, TrackGroupPanelInfo>();
  }

  registerPanel(panel: Panel, yStart: number, height: number) {
    if (exists(panel.trackKey)) {
      const track = globals.state.tracks[panel.trackKey];
      for (const trackId of getTrackIds(track)) {
        this.trackIdToTrackPanel.set(trackId, {panel, yStart});
      }
    } else if (exists(panel.trackGroupId)) {
      this.groupIdToTrackGroupPanel.set(panel.trackGroupId, {
        panel,
        yStart,
        height,
      });
    }
  }
}

export class FlowEventsRenderer {
  private getTrackGroupIdByTrackId(trackId: number): string | undefined {
    const trackKey = globals.trackManager.trackKeyByTrackId.get(trackId);
    return trackKey ? globals.state.tracks[trackKey].trackGroup : undefined;
  }

  private getTrackGroupYCoordinate(
    args: FlowEventsRendererArgs,
    trackId: number,
  ): number | undefined {
    const trackGroupId = this.getTrackGroupIdByTrackId(trackId);
    if (!trackGroupId) {
      return undefined;
    }
    const trackGroupInfo = args.groupIdToTrackGroupPanel.get(trackGroupId);
    if (!trackGroupInfo) {
      return undefined;
    }
    return (
      trackGroupInfo.yStart +
      trackGroupInfo.height -
      TRACK_GROUP_CONNECTION_OFFSET
    );
  }

  private getTrackYCoordinate(
    args: FlowEventsRendererArgs,
    trackId: number,
  ): number | undefined {
    return args.trackIdToTrackPanel.get(trackId)?.yStart;
  }

  private getYConnection(
    args: FlowEventsRendererArgs,
    trackId: number,
    rect?: SliceRect,
  ): {y: number; connection: ConnectionType} | undefined {
    if (!rect) {
      const y = this.getTrackGroupYCoordinate(args, trackId);
      if (y === undefined) {
        return undefined;
      }
      return {y, connection: 'TRACK_GROUP'};
    }
    const y =
      (this.getTrackYCoordinate(args, trackId) ?? 0) +
      rect.top +
      rect.height * 0.5;

    return {
      y: Math.min(Math.max(0, y), args.canvasHeight),
      connection: 'TRACK',
    };
  }

  private getXCoordinate(ts: time): number {
    return globals.timeline.visibleTimeScale.timeToPx(ts);
  }

  private getSliceRect(
    args: FlowEventsRendererArgs,
    point: FlowPoint,
  ): SliceRect | undefined {
    const trackPanel = args.trackIdToTrackPanel.get(point.trackId)?.panel;
    if (!trackPanel) {
      return undefined;
    }
    return trackPanel.getSliceRect?.(
      point.sliceStartTs,
      point.sliceEndTs,
      point.depth,
    );
  }

  render(ctx: CanvasRenderingContext2D, args: FlowEventsRendererArgs) {
    ctx.save();
    ctx.translate(TRACK_SHELL_WIDTH, 0);
    ctx.rect(0, 0, args.canvasWidth - TRACK_SHELL_WIDTH, args.canvasHeight);
    ctx.clip();

    globals.connectedFlows.forEach((flow) => {
      this.drawFlow(ctx, args, flow, CONNECTED_FLOW_HUE);
    });

    globals.selectedFlows.forEach((flow) => {
      const categories = getFlowCategories(flow);
      for (const cat of categories) {
        if (
          globals.visibleFlowCategories.get(cat) ||
          globals.visibleFlowCategories.get(ALL_CATEGORIES)
        ) {
          this.drawFlow(ctx, args, flow, SELECTED_FLOW_HUE);
          break;
        }
      }
    });

    ctx.restore();
  }

  private drawFlow(
    ctx: CanvasRenderingContext2D,
    args: FlowEventsRendererArgs,
    flow: Flow,
    hue: number,
  ) {
    const beginSliceRect = this.getSliceRect(args, flow.begin);
    const endSliceRect = this.getSliceRect(args, flow.end);

    const beginYConnection = this.getYConnection(
      args,
      flow.begin.trackId,
      beginSliceRect,
    );
    const endYConnection = this.getYConnection(
      args,
      flow.end.trackId,
      endSliceRect,
    );

    if (!beginYConnection || !endYConnection) {
      return;
    }

    let beginDir: LineDirection = 'LEFT';
    let endDir: LineDirection = 'RIGHT';
    if (beginYConnection.connection === 'TRACK_GROUP') {
      beginDir = beginYConnection.y > endYConnection.y ? 'DOWN' : 'UP';
    }
    if (endYConnection.connection === 'TRACK_GROUP') {
      endDir = endYConnection.y > beginYConnection.y ? 'DOWN' : 'UP';
    }

    const begin = {
      // If the flow goes to a descendant, we want to draw the arrow from the
      // beginning of the slice
      // rather from the end to avoid the flow arrow going backwards.
      x: this.getXCoordinate(
        flow.flowToDescendant ||
          flow.begin.sliceStartTs >= flow.end.sliceStartTs
          ? flow.begin.sliceStartTs
          : flow.begin.sliceEndTs,
      ),
      y: beginYConnection.y,
      dir: beginDir,
    };
    const end = {
      x: this.getXCoordinate(flow.end.sliceStartTs),
      y: endYConnection.y,
      dir: endDir,
    };
    const highlighted =
      flow.end.sliceId === globals.state.highlightedSliceId ||
      flow.begin.sliceId === globals.state.highlightedSliceId;
    const focused =
      flow.id === globals.state.focusedFlowIdLeft ||
      flow.id === globals.state.focusedFlowIdRight;

    let intensity = DEFAULT_FLOW_INTENSITY;
    let width = DEFAULT_FLOW_WIDTH;
    if (focused) {
      intensity = FOCUSED_FLOW_INTENSITY;
      width = FOCUSED_FLOW_WIDTH;
    }
    if (highlighted) {
      intensity = HIGHLIGHTED_FLOW_INTENSITY;
    }
    this.drawFlowArrow(ctx, begin, end, hue, intensity, width);
  }

  private getDeltaX(dir: LineDirection, offset: number): number {
    switch (dir) {
      case 'LEFT':
        return -offset;
      case 'RIGHT':
        return offset;
      case 'UP':
        return 0;
      case 'DOWN':
        return 0;
      default:
        return 0;
    }
  }

  private getDeltaY(dir: LineDirection, offset: number): number {
    switch (dir) {
      case 'LEFT':
        return 0;
      case 'RIGHT':
        return 0;
      case 'UP':
        return -offset;
      case 'DOWN':
        return offset;
      default:
        return 0;
    }
  }

  private drawFlowArrow(
    ctx: CanvasRenderingContext2D,
    begin: {x: number; y: number; dir: LineDirection},
    end: {x: number; y: number; dir: LineDirection},
    hue: number,
    intensity: number,
    width: number,
  ) {
    const hasArrowHead = Math.abs(begin.x - end.x) > 3 * TRIANGLE_SIZE;
    const END_OFFSET =
      (end.dir === 'RIGHT' || end.dir === 'LEFT') && hasArrowHead
        ? TRIANGLE_SIZE
        : 0;
    const color = `hsl(${hue}, 50%, ${intensity}%)`;
    // draw curved line from begin to end (bezier curve)
    ctx.strokeStyle = color;
    ctx.lineWidth = width;
    ctx.beginPath();
    ctx.moveTo(begin.x, begin.y);
    ctx.bezierCurveTo(
      begin.x - this.getDeltaX(begin.dir, BEZIER_OFFSET),
      begin.y - this.getDeltaY(begin.dir, BEZIER_OFFSET),
      end.x - this.getDeltaX(end.dir, BEZIER_OFFSET + END_OFFSET),
      end.y - this.getDeltaY(end.dir, BEZIER_OFFSET + END_OFFSET),
      end.x - this.getDeltaX(end.dir, END_OFFSET),
      end.y - this.getDeltaY(end.dir, END_OFFSET),
    );
    ctx.stroke();

    // TODO (andrewbb): probably we should add a parameter 'MarkerType' to be
    // able to choose what marker we want to draw _before_ the function call.
    // e.g. triangle, circle, square?
    if (begin.dir !== 'RIGHT' && begin.dir !== 'LEFT') {
      // draw a circle if we the line has a vertical connection
      ctx.fillStyle = color;
      ctx.beginPath();
      ctx.arc(begin.x, begin.y, 3, 0, 2 * Math.PI);
      ctx.closePath();
      ctx.fill();
    }

    if (end.dir !== 'RIGHT' && end.dir !== 'LEFT') {
      // draw a circle if we the line has a vertical connection
      ctx.fillStyle = color;
      ctx.beginPath();
      ctx.arc(end.x, end.y, CIRCLE_RADIUS, 0, 2 * Math.PI);
      ctx.closePath();
      ctx.fill();
    } else if (hasArrowHead) {
      this.drawArrowHead(end, ctx, color);
    }
  }

  private drawArrowHead(
    end: {x: number; y: number; dir: LineDirection},
    ctx: CanvasRenderingContext2D,
    color: string,
  ) {
    const dx = this.getDeltaX(end.dir, TRIANGLE_SIZE);
    const dy = this.getDeltaY(end.dir, TRIANGLE_SIZE);
    // draw small triangle
    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.moveTo(end.x, end.y);
    ctx.lineTo(end.x - dx - dy, end.y + dx - dy);
    ctx.lineTo(end.x - dx + dy, end.y - dx - dy);
    ctx.closePath();
    ctx.fill();
  }
}
