// 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.state.trackKeyByTrackId[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.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();
  }
}
