// 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 {Time} from '../base/time';
import {Actions} from '../common/actions';
import {randomColor} from '../common/colorizer';
import {AreaNote, Note} from '../common/state';
import {raf} from '../core/raf_scheduler';
import {Button} from '../widgets/button';

import {
  BottomTab,
  bottomTabRegistry,
  NewBottomTabArgs,
} from './bottom_tab';
import {TRACK_SHELL_WIDTH} from './css_constants';
import {globals} from './globals';
import {
  getMaxMajorTicks,
  TickGenerator,
  TickType,
  timeScaleForVisibleWindow,
} from './gridline_helper';
import {PanelSize} from './panel';
import {Panel} from './panel_container';
import {isTraceLoaded} from './sidebar';
import {Timestamp} from './widgets/timestamp';

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|AreaNote) {
  if (note.noteType === 'AREA') {
    return globals.state.areas[note.areaId].start;
  } else {
    return note.timestamp;
  }
}

export class NotesPanel implements Panel {
  readonly kind = 'panel';
  readonly selectable = false;
  readonly trackKey = undefined;

  hoveredX: null|number = null;

  constructor(readonly key: string) {}

  render(): m.Children {
    const allCollapsed = Object.values(globals.state.trackGroups)
      .every((group) => group.collapsed);

    return m(
      '.notes-panel',
      {
        onclick: (e: MouseEvent) => {
          const {x, y} = currentTargetOffset(e);
          this.onClick(x - TRACK_SHELL_WIDTH, y);
          e.stopPropagation();
        },
        onmousemove: (e: MouseEvent) => {
          this.hoveredX = currentTargetOffset(e).x - TRACK_SHELL_WIDTH;
          raf.scheduleRedraw();
        },
        mouseenter: (e: MouseEvent) => {
          this.hoveredX = currentTargetOffset(e).x - TRACK_SHELL_WIDTH;
          raf.scheduleRedraw();
        },
        onmouseout: () => {
          this.hoveredX = null;
          globals.dispatch(
            Actions.setHoveredNoteTimestamp({ts: Time.INVALID}));
        },
      },
      isTraceLoaded() ?
        [
          m('button',
            {
              onclick: (e: Event) => {
                e.preventDefault();
                if (allCollapsed) {
                  globals.commandManager.runCommand('dev.perfetto.CoreCommands#ExpandAllGroups');
                } else {
                  globals.commandManager.runCommand('dev.perfetto.CoreCommands#CollapseAllGroups');
                }
              },
            },
            m('i.material-icons',
              {title: allCollapsed ? 'Expand all' : 'Collapse all'},
              allCollapsed ? 'unfold_more' : 'unfold_less')),
          m('button',
            {
              onclick: (e: Event) => {
                e.preventDefault();
                globals.dispatch(Actions.clearAllPinnedTracks({}));
              },
            },
            m('i.material-icons',
              {title: 'Clear all pinned tracks'},
              'clear_all')),
        ] :
        '');
  }

  renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
    let aNoteIsHovered = false;

    ctx.fillStyle = '#999';
    ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);

    ctx.save();
    ctx.beginPath();
    ctx.rect(TRACK_SHELL_WIDTH, 0, size.width - TRACK_SHELL_WIDTH, size.height);
    ctx.clip();

    const span = globals.timeline.visibleTimeSpan;
    const {visibleTimeScale} = globals.timeline;
    if (size.width > TRACK_SHELL_WIDTH && span.duration > 0n) {
      const maxMajorTicks = getMaxMajorTicks(size.width - TRACK_SHELL_WIDTH);
      const map = timeScaleForVisibleWindow(TRACK_SHELL_WIDTH, size.width);
      const offset = globals.timestampOffset();
      const tickGen = new TickGenerator(span, maxMajorTicks, offset);
      for (const {type, time} of tickGen) {
        const px = Math.floor(map.timeToPx(time));
        if (type === TickType.MAJOR) {
          ctx.fillRect(px, 0, 1, size.height);
        }
      }
    }

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

    for (const note of Object.values(globals.state.notes)) {
      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 !== 'AREA' && !span.contains(timestamp)) ||
          (note.noteType === 'AREA' &&
           !span.contains(globals.state.areas[note.areaId].end) &&
           !span.contains(globals.state.areas[note.areaId].start))) {
        continue;
      }
      const currentIsHovered =
          this.hoveredX !== null && this.mouseOverNote(this.hoveredX, note);
      if (currentIsHovered) aNoteIsHovered = true;

      const selection = globals.state.currentSelection;
      const isSelected = selection !== null &&
          ((selection.kind === 'NOTE' && selection.id === note.id) ||
           (selection.kind === 'AREA' && selection.noteId === note.id));
      const x = visibleTimeScale.timeToPx(timestamp);
      const left = Math.floor(x + TRACK_SHELL_WIDTH);

      // Draw flag or marker.
      if (note.noteType === 'AREA') {
        const area = globals.state.areas[note.areaId];
        this.drawAreaMarker(
          ctx,
          left,
          Math.floor(visibleTimeScale.timeToPx(area.end) + TRACK_SHELL_WIDTH),
          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) {
      globals.dispatch(Actions.setHoveredNoteTimestamp({ts: Time.INVALID}));
    }

    // View preview note flag when hovering on notes panel.
    if (!aNoteIsHovered && this.hoveredX !== null) {
      const timestamp = visibleTimeScale.pxToHpTime(this.hoveredX).toTime();
      if (span.contains(timestamp)) {
        globals.dispatch(Actions.setHoveredNoteTimestamp({ts: timestamp}));
        const x = visibleTimeScale.timeToPx(timestamp);
        const left = Math.floor(x + TRACK_SHELL_WIDTH);
        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 >= TRACK_SHELL_WIDTH) {
      // 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, TRACK_SHELL_WIDTH);
    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, _: number) {
    if (x < 0) return;
    const {visibleTimeScale} = globals.timeline;
    const timestamp = visibleTimeScale.pxToHpTime(x).toTime();
    for (const note of Object.values(globals.state.notes)) {
      if (this.hoveredX !== null && this.mouseOverNote(this.hoveredX, note)) {
        if (note.noteType === 'AREA') {
          globals.makeSelection(
            Actions.reSelectArea({areaId: note.areaId, noteId: note.id}));
        } else {
          globals.makeSelection(Actions.selectNote({id: note.id}));
        }
        return;
      }
    }
    const color = randomColor();
    globals.makeSelection(Actions.addNote({timestamp, color}));
  }

  private mouseOverNote(x: number, note: AreaNote|Note): boolean {
    const timeScale = globals.timeline.visibleTimeScale;
    const noteX = timeScale.timeToPx(getStartTimestamp(note));
    if (note.noteType === 'AREA') {
      const noteArea = globals.state.areas[note.areaId];
      return (noteX <= x && x < noteX + AREA_TRIANGLE_WIDTH) ||
          (timeScale.timeToPx(noteArea.end) > x &&
           x > timeScale.timeToPx(noteArea.end) - AREA_TRIANGLE_WIDTH);
    } else {
      const width = FLAG_WIDTH;
      return noteX <= x && x < noteX + width;
    }
  }
}

interface NotesEditorTabConfig {
  id: string;
}

export class NotesEditorTab extends BottomTab<NotesEditorTabConfig> {
  static readonly kind = 'org.perfetto.NotesEditorTab';

  static create(args: NewBottomTabArgs<NotesEditorTabConfig>): NotesEditorTab {
    return new NotesEditorTab(args);
  }

  constructor(args: NewBottomTabArgs<NotesEditorTabConfig>) {
    super(args);
  }

  getTitle() {
    return 'Current Selection';
  }

  viewTab() {
    const note = globals.state.notes[this.config.id];
    if (note === undefined) {
      return m('.', `No Note with id ${this.config.id}`);
    }
    const startTime = getStartTimestamp(note);
    return m(
      '.notes-editor-panel',
      m('.notes-editor-panel-heading-bar',
        m('.notes-editor-panel-heading',
          `Annotation at `,
          m(Timestamp, {ts: startTime})),
        m('input[type=text]', {
          value: note.text,
          onchange: (e: InputEvent) => {
            const newText = (e.target as HTMLInputElement).value;
            globals.dispatch(Actions.changeNoteText({
              id: this.config.id,
              newText,
            }));
          },
        }),
        m('span.color-change', `Change color: `, m('input[type=color]', {
          value: note.color,
          onchange: (e: Event) => {
            const newColor = (e.target as HTMLInputElement).value;
            globals.dispatch(Actions.changeNoteColor({
              id: this.config.id,
              newColor,
            }));
          },
        })),
        m(Button, {
          label: 'Remove',
          icon: Icons.Delete,
          minimal: true,
          onclick: () => {
            globals.dispatch(Actions.removeNote({id: this.config.id}));
            globals.dispatch(Actions.setCurrentTab({tab: undefined}));
            raf.scheduleFullRedraw();
          },
        })),
    );
  }
}

bottomTabRegistry.register(NotesEditorTab);
