// Copyright (C) 2019 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 m from 'mithril';
import {currentTargetOffset} from '../base/dom_utils';
import {Icons} from '../base/semantic_icons';
import {randomColor} from '../public/lib/colorizer';
import {SpanNote, Note} from '../public/note';
import {raf} from '../core/raf_scheduler';
import {Button, ButtonBar} from '../widgets/button';
import {TRACK_SHELL_WIDTH} from './css_constants';
import {getMaxMajorTicks, generateTicks, TickType} from './gridline_helper';
import {Size2D} from '../base/geom';
import {Panel} from './panel_container';
import {Timestamp} from './widgets/timestamp';
import {assertUnreachable} from '../base/logging';
import {DetailsPanel} from '../public/details_panel';
import {TimeScale} from '../base/time_scale';
import {canvasClip} from '../base/canvas_utils';
import {Selection} from '../public/selection';
import {TraceImpl} from '../core/trace_impl';

const FLAG_WIDTH = 16;
const AREA_TRIANGLE_WIDTH = 10;
const FLAG = `\uE153`;

function toSummary(s: string) {
  const newlineIndex = s.indexOf('\n') > 0 ? s.indexOf('\n') : s.length;
  return s.slice(0, Math.min(newlineIndex, s.length, 16));
}

function getStartTimestamp(note: Note | SpanNote) {
  const noteType = note.noteType;
  switch (noteType) {
    case 'SPAN':
      return note.start;
    case 'DEFAULT':
      return note.timestamp;
    default:
      assertUnreachable(noteType);
  }
}

export class NotesPanel implements Panel {
  readonly kind = 'panel';
  readonly selectable = false;
  private readonly trace: TraceImpl;
  private timescale?: TimeScale; // The timescale from the last render()
  private hoveredX: null | number = null;
  private mouseDragging = false;

  constructor(trace: TraceImpl) {
    this.trace = trace;
  }

  render(): m.Children {
    const allCollapsed = this.trace.workspace.flatTracks.every(
      (n) => n.collapsed,
    );

    return m(
      '.notes-panel',
      {
        onmousedown: () => {
          // If the user clicks & drags, very likely they just want to measure
          // the time horizontally, not set a flag. This debouncing is done to
          // avoid setting accidental flags like measuring the time on the brush
          // timeline.
          this.mouseDragging = false;
        },
        onclick: (e: MouseEvent) => {
          if (!this.mouseDragging) {
            const x = currentTargetOffset(e).x - TRACK_SHELL_WIDTH;
            this.onClick(x);
            e.stopPropagation();
          }
        },
        onmousemove: (e: MouseEvent) => {
          this.mouseDragging = true;
          this.hoveredX = currentTargetOffset(e).x - TRACK_SHELL_WIDTH;
          raf.scheduleCanvasRedraw();
        },
        onmouseenter: (e: MouseEvent) => {
          this.hoveredX = currentTargetOffset(e).x - TRACK_SHELL_WIDTH;
          raf.scheduleCanvasRedraw();
        },
        onmouseout: () => {
          this.hoveredX = null;
          this.trace.timeline.hoveredNoteTimestamp = undefined;
        },
      },
      m(
        ButtonBar,
        {className: 'pf-toolbar'},
        m(Button, {
          onclick: (e: Event) => {
            e.preventDefault();
            if (allCollapsed) {
              this.trace.commands.runCommand(
                'perfetto.CoreCommands#ExpandAllGroups',
              );
            } else {
              this.trace.commands.runCommand(
                'perfetto.CoreCommands#CollapseAllGroups',
              );
            }
          },
          title: allCollapsed ? 'Expand all' : 'Collapse all',
          icon: allCollapsed ? 'unfold_more' : 'unfold_less',
          compact: true,
        }),
        m(Button, {
          onclick: (e: Event) => {
            e.preventDefault();
            this.trace.workspace.pinnedTracks.forEach((t) =>
              this.trace.workspace.unpinTrack(t),
            );
            raf.scheduleFullRedraw();
          },
          title: 'Clear all pinned tracks',
          icon: 'clear_all',
          compact: true,
        }),
        // TODO(stevegolton): Re-introduce this when we fix track filtering
        // m(TextInput, {
        //   placeholder: 'Filter tracks...',
        //   title:
        //     'Track filter - enter one or more comma-separated search terms',
        //   value: this.trace.state.trackFilterTerm,
        //   oninput: (e: Event) => {
        //     const filterTerm = (e.target as HTMLInputElement).value;
        //     this.trace.dispatch(Actions.setTrackFilterTerm({filterTerm}));
        //   },
        // }),
        // m(Button, {
        //   type: 'reset',
        //   icon: 'backspace',
        //   onclick: () => {
        //     this.trace.dispatch(
        //       Actions.setTrackFilterTerm({filterTerm: undefined}),
        //     );
        //   },
        //   title: 'Clear track filter',
        // }),
      ),
    );
  }

  renderCanvas(ctx: CanvasRenderingContext2D, size: Size2D) {
    ctx.fillStyle = '#999';
    ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);

    const trackSize = {...size, width: size.width - TRACK_SHELL_WIDTH};

    ctx.save();
    ctx.translate(TRACK_SHELL_WIDTH, 0);
    canvasClip(ctx, 0, 0, trackSize.width, trackSize.height);
    this.renderPanel(ctx, trackSize);
    ctx.restore();
  }

  private renderPanel(ctx: CanvasRenderingContext2D, size: Size2D): void {
    let aNoteIsHovered = false;

    const visibleWindow = this.trace.timeline.visibleWindow;
    const timescale = new TimeScale(visibleWindow, {
      left: 0,
      right: size.width,
    });
    const timespan = visibleWindow.toTimeSpan();

    this.timescale = timescale;

    if (size.width > 0 && timespan.duration > 0n) {
      const maxMajorTicks = getMaxMajorTicks(size.width);
      const offset = this.trace.timeline.timestampOffset();
      const tickGen = generateTicks(timespan, maxMajorTicks, offset);
      for (const {type, time} of tickGen) {
        const px = Math.floor(timescale.timeToPx(time));
        if (type === TickType.MAJOR) {
          ctx.fillRect(px, 0, 1, size.height);
        }
      }
    }

    ctx.textBaseline = 'bottom';
    ctx.font = '10px Helvetica';

    for (const note of this.trace.notes.notes.values()) {
      const timestamp = getStartTimestamp(note);
      // TODO(hjd): We should still render area selection marks in viewport is
      // *within* the area (e.g. both lhs and rhs are out of bounds).
      if (
        (note.noteType === 'DEFAULT' &&
          !visibleWindow.contains(note.timestamp)) ||
        (note.noteType === 'SPAN' &&
          !visibleWindow.overlaps(note.start, note.end))
      ) {
        continue;
      }
      const currentIsHovered =
        this.hoveredX !== null && this.hitTestNote(this.hoveredX, note);
      if (currentIsHovered) aNoteIsHovered = true;

      const selection = this.trace.selection.selection;
      const isSelected = selection.kind === 'note' && selection.id === note.id;
      const x = timescale.timeToPx(timestamp);
      const left = Math.floor(x);

      // Draw flag or marker.
      if (note.noteType === 'SPAN') {
        this.drawAreaMarker(
          ctx,
          left,
          Math.floor(timescale.timeToPx(note.end)),
          note.color,
          isSelected,
        );
      } else {
        this.drawFlag(ctx, left, size.height, note.color, isSelected);
      }

      if (note.text) {
        const summary = toSummary(note.text);
        const measured = ctx.measureText(summary);
        // Add a white semi-transparent background for the text.
        ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
        ctx.fillRect(
          left + FLAG_WIDTH + 2,
          size.height + 2,
          measured.width + 2,
          -12,
        );
        ctx.fillStyle = '#3c4b5d';
        ctx.fillText(summary, left + FLAG_WIDTH + 3, size.height + 1);
      }
    }

    // A real note is hovered so we don't need to see the preview line.
    // TODO(hjd): Change cursor to pointer here.
    if (aNoteIsHovered) {
      this.trace.timeline.hoveredNoteTimestamp = undefined;
    }

    // View preview note flag when hovering on notes panel.
    if (!aNoteIsHovered && this.hoveredX !== null) {
      const timestamp = timescale.pxToHpTime(this.hoveredX).toTime();
      if (visibleWindow.contains(timestamp)) {
        this.trace.timeline.hoveredNoteTimestamp = timestamp;
        const x = timescale.timeToPx(timestamp);
        const left = Math.floor(x);
        this.drawFlag(ctx, left, size.height, '#aaa', /* fill */ true);
      }
    }

    ctx.restore();
  }

  private drawAreaMarker(
    ctx: CanvasRenderingContext2D,
    x: number,
    xEnd: number,
    color: string,
    fill: boolean,
  ) {
    ctx.fillStyle = color;
    ctx.strokeStyle = color;
    const topOffset = 10;
    // Don't draw in the track shell section.
    if (x >= 0) {
      // Draw left triangle.
      ctx.beginPath();
      ctx.moveTo(x, topOffset);
      ctx.lineTo(x, topOffset + AREA_TRIANGLE_WIDTH);
      ctx.lineTo(x + AREA_TRIANGLE_WIDTH, topOffset);
      ctx.lineTo(x, topOffset);
      if (fill) ctx.fill();
      ctx.stroke();
    }
    // Draw right triangle.
    ctx.beginPath();
    ctx.moveTo(xEnd, topOffset);
    ctx.lineTo(xEnd, topOffset + AREA_TRIANGLE_WIDTH);
    ctx.lineTo(xEnd - AREA_TRIANGLE_WIDTH, topOffset);
    ctx.lineTo(xEnd, topOffset);
    if (fill) ctx.fill();
    ctx.stroke();

    // Start line after track shell section, join triangles.
    const startDraw = Math.max(x, 0);
    ctx.beginPath();
    ctx.moveTo(startDraw, topOffset);
    ctx.lineTo(xEnd, topOffset);
    ctx.stroke();
  }

  private drawFlag(
    ctx: CanvasRenderingContext2D,
    x: number,
    height: number,
    color: string,
    fill?: boolean,
  ) {
    const prevFont = ctx.font;
    const prevBaseline = ctx.textBaseline;
    ctx.textBaseline = 'alphabetic';
    // Adjust height for icon font.
    ctx.font = '24px Material Symbols Sharp';
    ctx.fillStyle = color;
    ctx.strokeStyle = color;
    // The ligatures have padding included that means the icon is not drawn
    // exactly at the x value. This adjusts for that.
    const iconPadding = 6;
    if (fill) {
      ctx.fillText(FLAG, x - iconPadding, height + 2);
    } else {
      ctx.strokeText(FLAG, x - iconPadding, height + 2.5);
    }
    ctx.font = prevFont;
    ctx.textBaseline = prevBaseline;
  }

  private onClick(x: number) {
    if (!this.timescale) {
      return;
    }

    // Select the hovered note, or create a new single note & select it
    if (x < 0) return;
    for (const note of this.trace.notes.notes.values()) {
      if (this.hoveredX !== null && this.hitTestNote(this.hoveredX, note)) {
        this.trace.selection.selectNote({id: note.id});
        return;
      }
    }
    const timestamp = this.timescale.pxToHpTime(x).toTime();
    const color = randomColor();
    const noteId = this.trace.notes.addNote({timestamp, color});
    this.trace.selection.selectNote({id: noteId});
  }

  private hitTestNote(x: number, note: SpanNote | Note): boolean {
    if (!this.timescale) {
      return false;
    }

    const timescale = this.timescale;
    const noteX = timescale.timeToPx(getStartTimestamp(note));
    if (note.noteType === 'SPAN') {
      return (
        (noteX <= x && x < noteX + AREA_TRIANGLE_WIDTH) ||
        (timescale.timeToPx(note.end) > x &&
          x > timescale.timeToPx(note.end) - AREA_TRIANGLE_WIDTH)
      );
    } else {
      const width = FLAG_WIDTH;
      return noteX <= x && x < noteX + width;
    }
  }
}

export class NotesEditorTab implements DetailsPanel {
  constructor(private trace: TraceImpl) {}

  render(selection: Selection) {
    if (selection.kind !== 'note') {
      return undefined;
    }

    const id = selection.id;

    const note = this.trace.notes.getNote(id);
    if (note === undefined) {
      return m('.', `No Note with id ${id}`);
    }
    const startTime = getStartTimestamp(note);
    return m(
      '.notes-editor-panel',
      {
        key: id, // Every note shoul get its own brand new DOM.
      },
      m(
        '.notes-editor-panel-heading-bar',
        m(
          '.notes-editor-panel-heading',
          `Annotation at `,
          m(Timestamp, {ts: startTime}),
        ),
        m('input[type=text]', {
          oncreate: (v: m.VnodeDOM) => {
            // NOTE: due to bad design decisions elsewhere this component is
            // rendered every time the mouse moves on the canvas. We cannot set
            // `value: note.text` as an input as that will clobber the input
            // value as we move the mouse.
            const inputElement = v.dom as HTMLInputElement;
            inputElement.value = note.text;
            inputElement.focus();
          },
          onchange: (e: InputEvent) => {
            const newText = (e.target as HTMLInputElement).value;
            this.trace.notes.changeNote(id, {text: newText});
          },
        }),
        m(
          'span.color-change',
          `Change color: `,
          m('input[type=color]', {
            value: note.color,
            onchange: (e: Event) => {
              const newColor = (e.target as HTMLInputElement).value;
              this.trace.notes.changeNote(id, {color: newColor});
            },
          }),
        ),
        m(Button, {
          label: 'Remove',
          icon: Icons.Delete,
          onclick: () => this.trace.notes.removeNote(id),
        }),
      ),
    );
  }
}
