// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this 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 {canvasClip, canvasSave} from '../base/canvas_utils';
import {classNames} from '../base/classnames';
import {Bounds2D, Size2D, VerticalBounds} from '../base/geom';
import {Icons} from '../base/semantic_icons';
import {TimeScale} from '../base/time_scale';
import {RequiredField} from '../base/utils';
import {calculateResolution} from '../common/resolution';
import {featureFlags} from '../core/feature_flags';
import {TrackRenderer} from '../core/track_manager';
import {TrackDescriptor, TrackRenderContext} from '../public/track';
import {TrackNode} from '../public/workspace';
import {Button} from '../widgets/button';
import {Popup, PopupPosition} from '../widgets/popup';
import {Tree, TreeNode} from '../widgets/tree';
import {SELECTION_FILL_COLOR, TRACK_SHELL_WIDTH} from './css_constants';
import {Panel} from './panel_container';
import {TrackWidget} from '../widgets/track_widget';
import {raf} from '../core/raf_scheduler';
import {Intent} from '../widgets/common';
import {TraceImpl} from '../core/trace_impl';

const SHOW_TRACK_DETAILS_BUTTON = featureFlags.register({
  id: 'showTrackDetailsButton',
  name: 'Show track details button',
  description: 'Show track details button in track shells.',
  defaultValue: false,
});

// Default height of a track element that has no track, or is collapsed.
// Note: This is designed to roughly match the height of a cpu slice track.
export const DEFAULT_TRACK_HEIGHT_PX = 30;

interface TrackPanelAttrs {
  readonly trace: TraceImpl;
  readonly node: TrackNode;
  readonly indentationLevel: number;
  readonly trackRenderer?: TrackRenderer;
  readonly revealOnCreate?: boolean;
  readonly topOffsetPx: number;
  readonly reorderable?: boolean;
}

export class TrackPanel implements Panel {
  readonly kind = 'panel';
  readonly selectable = true;
  readonly trackNode?: TrackNode;

  private readonly attrs: TrackPanelAttrs;

  constructor(attrs: TrackPanelAttrs) {
    this.attrs = attrs;
    this.trackNode = attrs.node;
  }

  get heightPx(): number {
    const {trackRenderer, node} = this.attrs;

    // If the node is a summary track and is expanded, shrink it to save
    // vertical real estate).
    if (node.isSummary && node.expanded) return DEFAULT_TRACK_HEIGHT_PX;

    // Otherwise return the height of the track, if we have one.
    return trackRenderer?.track.getHeight() ?? DEFAULT_TRACK_HEIGHT_PX;
  }

  render(): m.Children {
    const {
      node,
      indentationLevel,
      trackRenderer,
      revealOnCreate,
      topOffsetPx,
      reorderable = false,
    } = this.attrs;

    const error = trackRenderer?.getError();

    const buttons = [
      SHOW_TRACK_DETAILS_BUTTON.get() &&
        renderTrackDetailsButton(node, trackRenderer?.desc),
      trackRenderer?.track.getTrackShellButtons?.(),
      node.removable && renderCloseButton(node),
      // Can't pin groups.. yet!
      !node.hasChildren && renderPinButton(node),
      this.renderAreaSelectionCheckbox(node),
      error && renderCrashButton(error, trackRenderer?.desc.pluginId),
    ];

    let scrollIntoView = false;
    const tracks = this.attrs.trace.tracks;
    if (tracks.scrollToTrackNodeId === node.id) {
      tracks.scrollToTrackNodeId = undefined;
      scrollIntoView = true;
    }

    return m(TrackWidget, {
      id: node.id,
      title: node.title,
      path: node.fullPath.join('/'),
      heightPx: this.heightPx,
      error: Boolean(trackRenderer?.getError()),
      chips: trackRenderer?.desc.chips,
      indentationLevel,
      topOffsetPx,
      buttons,
      revealOnCreate: revealOnCreate || scrollIntoView,
      collapsible: node.hasChildren,
      collapsed: node.collapsed,
      highlight: this.isHighlighted(node),
      isSummary: node.isSummary,
      reorderable,
      onToggleCollapsed: () => {
        node.hasChildren && node.toggleCollapsed();
      },
      onTrackContentMouseMove: (pos, bounds) => {
        const timescale = this.getTimescaleForBounds(bounds);
        trackRenderer?.track.onMouseMove?.({
          ...pos,
          timescale,
        });
        raf.scheduleCanvasRedraw();
      },
      onTrackContentMouseOut: () => {
        trackRenderer?.track.onMouseOut?.();
        raf.scheduleCanvasRedraw();
      },
      onTrackContentClick: (pos, bounds) => {
        const timescale = this.getTimescaleForBounds(bounds);
        raf.scheduleCanvasRedraw();
        return (
          trackRenderer?.track.onMouseClick?.({
            ...pos,
            timescale,
          }) ?? false
        );
      },
      onupdate: () => {
        trackRenderer?.track.onFullRedraw?.();
      },
      onMoveBefore: (nodeId: string) => {
        const targetNode = node.workspace?.getTrackById(nodeId);
        if (targetNode !== undefined) {
          // Insert the target node before this one
          targetNode.parent?.addChildBefore(targetNode, node);
        }
      },
      onMoveAfter: (nodeId: string) => {
        const targetNode = node.workspace?.getTrackById(nodeId);
        if (targetNode !== undefined) {
          // Insert the target node after this one
          targetNode.parent?.addChildAfter(targetNode, node);
        }
      },
    });
  }

  renderCanvas(ctx: CanvasRenderingContext2D, size: Size2D) {
    const {trackRenderer: tr, node} = this.attrs;

    // Don't render if expanded and isSummary
    if (node.isSummary && node.expanded) {
      return;
    }

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

    using _ = canvasSave(ctx);
    ctx.translate(TRACK_SHELL_WIDTH, 0);
    canvasClip(ctx, 0, 0, trackSize.width, trackSize.height);

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

    if (tr) {
      if (!tr.getError()) {
        const trackRenderCtx: TrackRenderContext = {
          trackUri: tr.desc.uri,
          visibleWindow,
          size: trackSize,
          resolution: calculateResolution(visibleWindow, trackSize.width),
          ctx,
          timescale,
        };
        tr.render(trackRenderCtx);
      }
    }

    this.highlightIfTrackInAreaSelection(ctx, timescale, node, trackSize);
  }

  getSliceVerticalBounds(depth: number): VerticalBounds | undefined {
    if (this.attrs.trackRenderer === undefined) {
      return undefined;
    }
    return this.attrs.trackRenderer.track.getSliceVerticalBounds?.(depth);
  }

  private getTimescaleForBounds(bounds: Bounds2D) {
    const timeWindow = this.attrs.trace.timeline.visibleWindow;
    return new TimeScale(timeWindow, {
      left: 0,
      right: bounds.right - bounds.left,
    });
  }

  private isHighlighted(node: TrackNode) {
    // The track should be highlighted if the current search result matches this
    // track or one of its children.
    const searchIndex = this.attrs.trace.search.resultIndex;
    const searchResults = this.attrs.trace.search.searchResults;

    if (searchIndex !== -1 && searchResults !== undefined) {
      const uri = searchResults.trackUris[searchIndex];
      // Highlight if this or any children match the search results
      if (uri === node.uri || node.flatTracks.find((t) => t.uri === uri)) {
        return true;
      }
    }

    const curSelection = this.attrs.trace.selection;
    if (
      curSelection.selection.kind === 'track' &&
      curSelection.selection.trackUri === node.uri
    ) {
      return true;
    }

    return false;
  }

  private highlightIfTrackInAreaSelection(
    ctx: CanvasRenderingContext2D,
    timescale: TimeScale,
    node: TrackNode,
    size: Size2D,
  ) {
    const selection = this.attrs.trace.selection.selection;
    if (selection.kind !== 'area') {
      return;
    }

    const tracksWithUris = node.flatTracks.filter(
      (t) => t.uri !== undefined,
    ) as ReadonlyArray<RequiredField<TrackNode, 'uri'>>;

    let selected = false;
    if (node.isSummary) {
      selected = tracksWithUris.some((track) =>
        selection.trackUris.includes(track.uri),
      );
    } else {
      if (node.uri) {
        selected = selection.trackUris.includes(node.uri);
      }
    }

    if (selected) {
      const selectedAreaDuration = selection.end - selection.start;
      ctx.fillStyle = SELECTION_FILL_COLOR;
      ctx.fillRect(
        timescale.timeToPx(selection.start),
        0,
        timescale.durationToPx(selectedAreaDuration),
        size.height,
      );
    }
  }

  private renderAreaSelectionCheckbox(node: TrackNode): m.Children {
    const selectionManager = this.attrs.trace.selection;
    const selection = selectionManager.selection;
    if (selection.kind === 'area') {
      if (node.isSummary) {
        const tracksWithUris = node.flatTracks.filter(
          (t) => t.uri !== undefined,
        ) as ReadonlyArray<RequiredField<TrackNode, 'uri'>>;
        // Check if any nodes within are selected
        const childTracksInSelection = tracksWithUris.map((t) =>
          selection.trackUris.includes(t.uri),
        );
        if (childTracksInSelection.every((b) => b)) {
          return m(Button, {
            onclick: (e: MouseEvent) => {
              const uris = tracksWithUris.map((t) => t.uri);
              selectionManager.toggleGroupAreaSelection(uris);
              e.stopPropagation();
            },
            compact: true,
            icon: Icons.Checkbox,
            title: 'Remove child tracks from selection',
          });
        } else if (childTracksInSelection.some((b) => b)) {
          return m(Button, {
            onclick: (e: MouseEvent) => {
              const uris = tracksWithUris.map((t) => t.uri);
              selectionManager.toggleGroupAreaSelection(uris);
              e.stopPropagation();
            },
            compact: true,
            icon: Icons.IndeterminateCheckbox,
            title: 'Add remaining child tracks to selection',
          });
        } else {
          return m(Button, {
            onclick: (e: MouseEvent) => {
              const uris = tracksWithUris.map((t) => t.uri);
              selectionManager.toggleGroupAreaSelection(uris);
              e.stopPropagation();
            },
            compact: true,
            icon: Icons.BlankCheckbox,
            title: 'Add child tracks to selection',
          });
        }
      } else {
        const nodeUri = node.uri;
        if (nodeUri) {
          return (
            selection.kind === 'area' &&
            m(Button, {
              onclick: (e: MouseEvent) => {
                selectionManager.toggleTrackAreaSelection(nodeUri);
                e.stopPropagation();
              },
              compact: true,
              ...(selection.trackUris.includes(nodeUri)
                ? {icon: Icons.Checkbox, title: 'Remove track'}
                : {icon: Icons.BlankCheckbox, title: 'Add track to selection'}),
            })
          );
        }
      }
    }
    return undefined;
  }
}

function renderCrashButton(error: Error, pluginId?: string) {
  return m(
    Popup,
    {
      trigger: m(Button, {
        icon: Icons.Crashed,
        compact: true,
      }),
    },
    m(
      '.pf-track-crash-popup',
      m('span', 'This track has crashed.'),
      pluginId && m('span', `Owning plugin: ${pluginId}`),
      m(Button, {
        label: 'View & Report Crash',
        intent: Intent.Primary,
        className: Popup.DISMISS_POPUP_GROUP_CLASS,
        onclick: () => {
          throw error;
        },
      }),
      // TODO(stevegolton): In the future we should provide a quick way to
      // disable the plugin, or provide a link to the plugin page, but this
      // relies on the plugin page being fully functional.
    ),
  );
}

function renderCloseButton(node: TrackNode) {
  return m(Button, {
    onclick: (e) => {
      node.remove();
      e.stopPropagation();
    },
    icon: Icons.Close,
    title: 'Close track',
    compact: true,
  });
}

function renderPinButton(node: TrackNode): m.Children {
  const isPinned = node.isPinned;
  return m(Button, {
    className: classNames(!isPinned && 'pf-visible-on-hover'),
    onclick: (e) => {
      isPinned ? node.unpin() : node.pin();
      e.stopPropagation();
    },
    icon: Icons.Pin,
    iconFilled: isPinned,
    title: isPinned ? 'Unpin' : 'Pin to top',
    compact: true,
  });
}

function renderTrackDetailsButton(
  node: TrackNode,
  td?: TrackDescriptor,
): m.Children {
  let parent = node.parent;
  let fullPath: m.ChildArray = [node.title];
  while (parent && parent instanceof TrackNode) {
    fullPath = [parent.title, ' \u2023 ', ...fullPath];
    parent = parent.parent;
  }
  return m(
    Popup,
    {
      trigger: m(Button, {
        className: 'pf-visible-on-hover',
        icon: 'info',
        title: 'Show track details',
        compact: true,
      }),
      position: PopupPosition.Bottom,
    },
    m(
      '.pf-track-details-dropdown',
      m(
        Tree,
        m(TreeNode, {left: 'Track Node ID', right: node.id}),
        m(TreeNode, {left: 'Collapsed', right: `${node.collapsed}`}),
        m(TreeNode, {left: 'URI', right: node.uri}),
        m(TreeNode, {left: 'Is Summary Track', right: `${node.isSummary}`}),
        m(TreeNode, {
          left: 'SortOrder',
          right: node.sortOrder ?? '0 (undefined)',
        }),
        m(TreeNode, {left: 'Path', right: fullPath}),
        m(TreeNode, {left: 'Title', right: node.title}),
        m(TreeNode, {
          left: 'Workspace',
          right: node.workspace?.title ?? '[no workspace]',
        }),
        td && m(TreeNode, {left: 'Plugin ID', right: td.pluginId}),
        td &&
          m(
            TreeNode,
            {left: 'Tags'},
            td.tags &&
              Object.entries(td.tags).map(([key, value]) => {
                return m(TreeNode, {left: key, right: value?.toString()});
              }),
          ),
      ),
    ),
  );
}
