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