/**
 * @license
 * Copyright 2021 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '@polymer/paper-button/paper-button';
import '@polymer/paper-card/paper-card';
import '@polymer/paper-checkbox/paper-checkbox';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu';
import '@polymer/paper-fab/paper-fab';
import '@polymer/paper-icon-button/paper-icon-button';
import '@polymer/paper-item/paper-item';
import '@polymer/paper-listbox/paper-listbox';
import '@polymer/paper-tooltip/paper-tooltip';
import {of, EMPTY, Subject} from 'rxjs';
import {switchMap, delay} from 'rxjs/operators';

import '../../../elements/shared/gr-button/gr-button';
import {pluralize} from '../../../utils/string-util';
import {fire} from '../../../utils/event-util';
import {DiffInfo} from '../../../types/diff';
import {assertIsDefined} from '../../../utils/common-util';
import {css, html, LitElement, TemplateResult} from 'lit';
import {property} from 'lit/decorators.js';
import {subscribe} from '../../../elements/lit/subscription-controller';

import {
  ContextButtonType,
  DiffContextButtonHoveredDetail,
  RenderPreferences,
  SyntaxBlock,
} from '../../../api/diff';

import {GrDiffGroup, hideInContextControl} from '../gr-diff/gr-diff-group';
import {isNewDiff} from '../../diff/gr-diff/gr-diff-utils';

declare global {
  interface HTMLElementEventMap {
    'diff-context-button-hovered': CustomEvent<DiffContextButtonHoveredDetail>;
  }
}

const PARTIAL_CONTEXT_AMOUNT = 10;

/**
 * Traverses a hierarchical structure of syntax blocks and
 * finds the most local/nested block that can be associated line.
 * It finds the closest block that contains the whole line and
 * returns the whole path from the syntax layer (blocks) sent as parameter
 * to the most nested block - the complete path from the top to bottom layer of
 * a syntax tree. Example: [myNamespace, MyClass, myMethod1, aLocalFunctionInsideMethod1]
 *
 * @param lineNum line number for the targeted line.
 * @param blocks Blocks for a specific syntax level in the file (to allow recursive calls)
 */
function findBlockTreePathForLine(
  lineNum: number,
  blocks?: SyntaxBlock[]
): SyntaxBlock[] {
  const containingBlock = blocks?.find(
    ({range}) => range.start_line < lineNum && range.end_line > lineNum
  );
  if (!containingBlock) return [];
  const innerPathInChild = findBlockTreePathForLine(
    lineNum,
    containingBlock?.children
  );
  return [containingBlock].concat(innerPathInChild);
}

export type GrContextControlsShowConfig = 'above' | 'below' | 'both';

export function getShowConfig(
  showAbove: boolean,
  showBelow: boolean
): GrContextControlsShowConfig {
  if (showAbove && !showBelow) return 'above';
  if (!showAbove && showBelow) return 'below';

  // Note that !showAbove && !showBelow also intentionally returns 'both'.
  // This means the file is completely collapsed, which is unusual, but at least
  // happens in one test.
  return 'both';
}

export class GrContextControls extends LitElement {
  @property({type: Object}) renderPreferences?: RenderPreferences;

  @property({type: Object}) diff?: DiffInfo;

  @property({type: Object}) group?: GrDiffGroup;

  @property({type: String, reflect: true})
  showConfig: GrContextControlsShowConfig = 'both';

  private expandButtonsHover = new Subject<{
    eventType: 'enter' | 'leave';
    buttonType: ContextButtonType;
    linesToExpand: number;
  }>();

  static override styles = css`
    :host {
      display: flex;
      justify-content: center;
      flex-direction: column;
      position: relative;
    }

    :host([showConfig='above']) {
      justify-content: flex-end;
      margin-top: calc(-1px - var(--line-height-normal) - var(--spacing-s));
      margin-bottom: var(--gr-context-controls-margin-bottom);
      height: calc(var(--line-height-normal) + var(--spacing-s));
      .horizontalFlex {
        align-items: end;
      }
    }

    :host([showConfig='below']) {
      justify-content: flex-start;
      margin-top: 1px;
      margin-bottom: calc(0px - var(--line-height-normal) - var(--spacing-s));
      .horizontalFlex {
        align-items: start;
      }
    }

    :host([showConfig='both']) {
      margin-top: calc(0px - var(--line-height-normal) - var(--spacing-s));
      margin-bottom: calc(0px - var(--line-height-normal) - var(--spacing-s));
      height: calc(
        2 * var(--line-height-normal) + 2 * var(--spacing-s) +
          var(--divider-height)
      );
      .horizontalFlex {
        align-items: center;
      }
    }

    .contextControlButton {
      background-color: var(--default-button-background-color);
      font: var(--context-control-button-font, inherit);
    }

    paper-button {
      text-transform: none;
      align-items: center;
      background-color: var(--background-color);
      font-family: inherit;
      margin: var(--margin, 0);
      min-width: var(--border, 0);
      color: var(--diff-context-control-color);
      border: solid var(--border-color);
      border-width: 1px;
      border-radius: var(--border-radius);
      padding: var(--spacing-s) var(--spacing-l);
    }

    paper-button:hover {
      /* same as defined in gr-button */
      background: rgba(0, 0, 0, 0.12);
    }
    paper-button:focus-visible {
      /* paper-button sets this to 0, thus preventing focus-based styling. */
      outline-width: 1px;
    }

    .aboveBelowButtons {
      display: flex;
      flex-direction: column;
      justify-content: center;
      margin-left: var(--spacing-m);
      position: relative;
    }
    .aboveBelowButtons:first-child {
      margin-left: 0;
      /* Places a default background layer behind the "all button" that can have opacity */
      background-color: var(--default-button-background-color);
    }

    .horizontalFlex {
      display: flex;
      justify-content: center;
      align-items: var(--gr-context-controls-horizontal-align-items, center);
    }

    .aboveButton {
      border-bottom-width: 0;
      border-bottom-right-radius: 0;
      border-bottom-left-radius: 0;
      padding: var(--spacing-xxs) var(--spacing-l);
    }
    .belowButton {
      border-top-width: 0;
      border-top-left-radius: 0;
      border-top-right-radius: 0;
      padding: var(--spacing-xxs) var(--spacing-l);
      margin-top: calc(var(--divider-height) + 2 * var(--spacing-xxs));
    }
    .belowButton:first-child {
      margin-top: 0;
    }
    .breadcrumbTooltip {
      white-space: nowrap;
    }
  `;

  constructor() {
    super();
    this.setupButtonHoverHandler();
  }

  private showBoth() {
    return this.showConfig === 'both';
  }

  private showAbove() {
    return this.showBoth() || this.showConfig === 'above';
  }

  private showBelow() {
    return this.showBoth() || this.showConfig === 'below';
  }

  private setupButtonHoverHandler() {
    subscribe(
      this,
      () =>
        this.expandButtonsHover.pipe(
          switchMap(e => {
            if (e.eventType === 'leave') {
              // cancel any previous delay
              // for mouse enter
              return EMPTY;
            }
            return of(e).pipe(delay(500));
          })
        ),
      ({buttonType, linesToExpand}) => {
        fire(this, 'diff-context-button-hovered', {
          buttonType,
          linesToExpand,
        });
      }
    );
  }

  private numLines() {
    assertIsDefined(this.group);
    // In context groups, there is the same number of lines left and right
    const left = this.group.lineRange.left;
    // Both start and end inclusive, so we need to add 1.
    return left.end_line - left.start_line + 1;
  }

  private createExpandAllButtonContainer() {
    return html` <div class="gr-diff aboveBelowButtons fullExpansion">
      ${this.createContextButton(ContextButtonType.ALL, this.numLines())}
    </div>`;
  }

  /**
   * Creates a specific expansion button (e.g. +X common lines, +10, +Block).
   */
  private createContextButton(
    type: ContextButtonType,
    linesToExpand: number,
    tooltip?: TemplateResult
  ) {
    if (!this.group) return;
    let text = '';
    let groups: GrDiffGroup[] = []; // The groups that replace this one if tapped.
    let ariaLabel = '';
    let classes = 'contextControlButton showContext ';

    if (type === ContextButtonType.ALL) {
      text = `+${pluralize(linesToExpand, 'common line')}`;
      ariaLabel = `Show ${pluralize(linesToExpand, 'common line')}`;
      classes += this.showBoth()
        ? 'centeredButton'
        : this.showAbove()
        ? 'aboveButton'
        : 'belowButton';
      if (this.group?.hasSkipGroup()) {
        // Expanding content would require load of more data
        text += ' (too large)';
      }
      groups.push(...this.group.contextGroups);
    } else if (type === ContextButtonType.ABOVE) {
      groups = hideInContextControl(
        this.group.contextGroups,
        linesToExpand,
        this.numLines()
      );
      text = `+${linesToExpand}`;
      classes += 'aboveButton';
      ariaLabel = `Show ${pluralize(linesToExpand, 'line')} above`;
    } else if (type === ContextButtonType.BELOW) {
      groups = hideInContextControl(
        this.group.contextGroups,
        0,
        this.numLines() - linesToExpand
      );
      text = `+${linesToExpand}`;
      classes += 'belowButton';
      ariaLabel = `Show ${pluralize(linesToExpand, 'line')} below`;
    } else if (type === ContextButtonType.BLOCK_ABOVE) {
      groups = hideInContextControl(
        this.group.contextGroups,
        linesToExpand,
        this.numLines()
      );
      text = '+Block';
      classes += 'aboveButton';
      ariaLabel = 'Show block above';
    } else if (type === ContextButtonType.BLOCK_BELOW) {
      groups = hideInContextControl(
        this.group.contextGroups,
        0,
        this.numLines() - linesToExpand
      );
      text = '+Block';
      classes += 'belowButton';
      ariaLabel = 'Show block below';
    }
    const expandHandler = this.createExpansionHandler(
      linesToExpand,
      type,
      groups
    );

    const mouseHandler = (eventType: 'enter' | 'leave') => {
      this.expandButtonsHover.next({
        eventType,
        buttonType: type,
        linesToExpand,
      });
    };

    const button = html` <paper-button
      class=${classes}
      aria-label=${ariaLabel}
      @click=${expandHandler}
      @mouseenter=${() => mouseHandler('enter')}
      @mouseleave=${() => mouseHandler('leave')}
    >
      <span class="showContext">${text}</span>
      ${tooltip}
    </paper-button>`;
    return button;
  }

  private createExpansionHandler(
    linesToExpand: number,
    type: ContextButtonType,
    groups: GrDiffGroup[]
  ) {
    return (e: Event) => {
      assertIsDefined(this.group);
      e.stopPropagation();
      if (type === ContextButtonType.ALL && this.group?.hasSkipGroup()) {
        fire(this, 'content-load-needed', {
          lineRange: this.group.lineRange,
        });
      } else {
        fire(this, 'diff-context-expanded', {
          numLines: this.numLines(),
          buttonType: type,
          expandedLines: linesToExpand,
        });
        fire(this, 'diff-context-expanded-internal', {
          contextGroup: this.group,
          groups,
          numLines: this.numLines(),
          buttonType: type,
          expandedLines: linesToExpand,
        });
      }
    };
  }

  private showPartialLinks() {
    return this.numLines() > PARTIAL_CONTEXT_AMOUNT;
  }

  /**
   * Creates a container div with partial (+10) expansion buttons (above and/or below).
   */
  private createPartialExpansionButtons() {
    if (!this.showPartialLinks()) {
      return undefined;
    }
    let aboveButton;
    let belowButton;
    if (this.showAbove()) {
      aboveButton = this.createContextButton(
        ContextButtonType.ABOVE,
        PARTIAL_CONTEXT_AMOUNT
      );
    }
    if (this.showBelow()) {
      belowButton = this.createContextButton(
        ContextButtonType.BELOW,
        PARTIAL_CONTEXT_AMOUNT
      );
    }
    return aboveButton || belowButton
      ? html` <div class="aboveBelowButtons partialExpansion">
          ${aboveButton} ${belowButton}
        </div>`
      : undefined;
  }

  /**
   * Creates a container div with block expansion buttons (above and/or below).
   */
  private createBlockExpansionButtons() {
    assertIsDefined(this.group, 'group');
    if (
      !this.showPartialLinks() ||
      !this.renderPreferences?.use_block_expansion ||
      this.group?.hasSkipGroup()
    ) {
      return undefined;
    }
    let aboveBlockButton;
    let belowBlockButton;
    if (this.showAbove()) {
      aboveBlockButton = this.createBlockButton(
        ContextButtonType.BLOCK_ABOVE,
        this.numLines(),
        this.group.lineRange.right.start_line - 1
      );
    }
    if (this.showBelow()) {
      belowBlockButton = this.createBlockButton(
        ContextButtonType.BLOCK_BELOW,
        this.numLines(),
        this.group.lineRange.right.end_line + 1
      );
    }
    if (aboveBlockButton || belowBlockButton) {
      return html` <div class="aboveBelowButtons blockExpansion">
        ${aboveBlockButton} ${belowBlockButton}
      </div>`;
    }
    return undefined;
  }

  private createBlockButtonTooltip(
    buttonType: ContextButtonType,
    syntaxPath: SyntaxBlock[],
    linesToExpand: number
  ) {
    // Create breadcrumb string:
    // myNamespace > MyClass > myMethod1 > aLocalFunctionInsideMethod1 > (anonymous)
    const tooltipText = syntaxPath.length
      ? syntaxPath.map(b => b.name || '(anonymous)').join(' > ')
      : `${linesToExpand} common lines`;

    const position =
      buttonType === ContextButtonType.BLOCK_ABOVE ? 'top' : 'bottom';
    return html`<paper-tooltip offset="10" position=${position}
      ><div class="breadcrumbTooltip">${tooltipText}</div></paper-tooltip
    >`;
  }

  private createBlockButton(
    buttonType: ContextButtonType,
    numLines: number,
    referenceLine: number
  ) {
    if (!this.diff?.meta_b) return;
    const syntaxTree = this.diff.meta_b.syntax_tree;
    const outlineSyntaxPath = findBlockTreePathForLine(
      referenceLine,
      syntaxTree
    );
    let linesToExpand = numLines;
    if (outlineSyntaxPath.length) {
      const {range} = outlineSyntaxPath[outlineSyntaxPath.length - 1];
      const targetLine =
        buttonType === ContextButtonType.BLOCK_ABOVE
          ? range.end_line
          : range.start_line;
      const distanceToTargetLine = Math.abs(targetLine - referenceLine);
      if (distanceToTargetLine < numLines) {
        linesToExpand = distanceToTargetLine;
      }
    }
    const tooltip = this.createBlockButtonTooltip(
      buttonType,
      outlineSyntaxPath,
      linesToExpand
    );
    return this.createContextButton(buttonType, linesToExpand, tooltip);
  }

  private hasValidProperties() {
    return !!(this.diff && this.group?.contextGroups?.length);
  }

  override render() {
    if (!this.hasValidProperties()) {
      console.error('Invalid properties for gr-context-controls!');
      return html`<p>invalid properties</p>`;
    }
    return html`
      <div class="horizontalFlex">
        ${this.createExpandAllButtonContainer()}
        ${this.createPartialExpansionButtons()}
        ${this.createBlockExpansionButtons()}
      </div>
    `;
  }
}
if (!isNewDiff()) {
  customElements.define('gr-context-controls', GrContextControls);
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-context-controls': LitElement;
  }
}
