/**
 * @license
 * Copyright 2021 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../../elements/shared/gr-tooltip-content/gr-tooltip-content';
import {EMPTY, of, Subject} from 'rxjs';
import {delay, switchMap} from 'rxjs/operators';
import '../../../elements/shared/gr-button/gr-button';
import {pluralize} from '../../../utils/string-util';
import {fire} from '../../../utils/event-util';
import {assertIsDefined} from '../../../utils/common-util';
import {css, html, LitElement, nothing, PropertyValues} from 'lit';
import {property, state} from 'lit/decorators.js';
import {subscribe} from '../../../elements/lit/subscription-controller';
import {
  ContextButtonType,
  DiffContextButtonHoveredDetail,
  RenderPreferences,
  SyntaxBlock,
} from '../../../api/diff';
import {
  GrDiffGroup,
  GrDiffGroupType,
  hideInContextControl,
} from '../gr-diff/gr-diff-group';
import {resolve} from '../../../models/dependency';
import {diffModelToken} from '../gr-diff-model/gr-diff-model';

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);
}

/**
 * 'above': Typically only for the context controls at the end of a file. So
 *          only show buttons "above" the middle line of the context control
 *          section.
 * 'below': Typically only for the context controls at the beginning of a file.
 *          So only show buttons "below" the middle line of the context control
 *          section.
 * 'both': Typically for the context controls in the middle of a file. So show
 *         two buttons, one for expanding from the top and one for expanding
 *         from the bottom.
 */
export type GrContextControlsShowConfig = 'above' | 'below' | 'both';

export function getShowConfig(group?: GrDiffGroup, lineCountLeft = 0) {
  const above = showAbove(group, lineCountLeft);
  const below = showBelow(group, lineCountLeft);

  if (above && !below) return 'above';
  if (!above && below) 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';
}

/** See GrContextControlsShowConfig for explanation of "above". */
export function showAbove(group?: GrDiffGroup, lineCountLeft = 0) {
  if (group?.type !== GrDiffGroupType.CONTEXT_CONTROL) return false;

  // Note that we could as well use `right.start_line` here. And below we only
  // use `left`, because we are comparing with `lineCountLeft`. But that is
  // just an arbitrary choice.
  const leftStart = group.lineRange.left.start_line;
  const firstGroupIsSkipped = !!group.contextGroups[0].skip;
  if (leftStart > 1 && !firstGroupIsSkipped) return true;

  const leftEnd = group.lineRange.left.end_line;
  const containsWholeFile = lineCountLeft === leftEnd - leftStart + 1;
  return containsWholeFile;
}

/** See GrContextControlsShowConfig for explanation of "below". */
export function showBelow(group?: GrDiffGroup, lineCountLeft = 0) {
  if (group?.type !== GrDiffGroupType.CONTEXT_CONTROL) return false;

  // Note that we could as well use `right.start_line` here. But we would then
  // require a `lineCountRight` parameter for making the comparison.
  const leftEnd = group.lineRange.left.end_line;
  const lastGroupIsSkipped =
    !!group.contextGroups[group.contextGroups.length - 1].skip;

  return leftEnd < lineCountLeft && !lastGroupIsSkipped;
}

interface ContextButtonTooltip {
  title: string;
  positionBelow: boolean;
}

/**
 * Renders context control buttons such as "+23 lines" or "+Block". It is only
 * meant to be used to be rendered into a diff table cell of its parent
 * component <gr-context-controls-section>.
 */
export class GrContextControls extends LitElement {
  @property({type: Object}) group?: GrDiffGroup;

  // This is just a property (and not a state), because we want to "reflect".
  @property({type: String, reflect: true})
  showConfig: GrContextControlsShowConfig = 'both';

  @state() syntaxTreeRight?: SyntaxBlock[];

  @state() renderPreferences?: RenderPreferences;

  @state() lineCountLeft = 0;

  private readonly getDiffModel = resolve(this, diffModelToken);

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

  static override get styles() {
    return [
      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);
        }

        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);
        }
        button:hover {
          background: rgba(0, 0, 0, 0.12);
        }
        button:focus-visible {
          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;
        }
        .unrelatedChanges {
          color: var(--primary-button-text-color);
          background-color: var(--primary-button-background-color);

          &:hover {
            // TODO(anuragpathak): Update hover colors as per specification.
            color: var(--primary-button-text-color);
            background-color: var(--primary-button-background-color);
          }
        }
      `,
    ];
  }

  constructor() {
    super();
    this.setupButtonHoverHandler();
    subscribe(
      this,
      () => this.getDiffModel().syntaxTreeRight$,
      syntaxTree => (this.syntaxTreeRight = syntaxTree)
    );
    subscribe(
      this,
      () => this.getDiffModel().renderPrefs$,
      renderPrefs => (this.renderPreferences = renderPrefs)
    );
    subscribe(
      this,
      () => this.getDiffModel().lineCountLeft$,
      lineCountLeft => {
        this.lineCountLeft = lineCountLeft;
        this.updateShowConfig();
      }
    );
  }

  override willUpdate(changedProperties: PropertyValues) {
    if (changedProperties.has('group')) this.updateShowConfig();
  }

  private updateShowConfig() {
    this.showConfig = getShowConfig(this.group, this.lineCountLeft);
  }

  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="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?: ContextButtonTooltip
  ) {
    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) {
      if (this.group.hasNonCommonDeltaGroup()) {
        text = '+ Unrelated changes';
        ariaLabel = 'Show unrelated changes';
        classes += ' unrelatedChanges ';
      } else {
        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,
      });
    };

    let button = html` <button
      class=${classes}
      aria-label=${ariaLabel}
      @click=${expandHandler}
      @mouseenter=${() => mouseHandler('enter')}
      @mouseleave=${() => mouseHandler('leave')}
    >
      <span class="showContext">${text}</span>
    </button>`;
    if (tooltip) {
      button = html`<gr-tooltip-content
        class="breadcrumbTooltip"
        has-tooltip
        title=${tooltip.title}
        ?position-below=${tooltip.positionBelow}
      >
        ${button}
      </gr-tooltip-content>`;
    }
    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-new', {
          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() || this.group?.hasNonCommonDeltaGroup()) {
      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() ||
      this.group?.hasNonCommonDeltaGroup()
    ) {
      return undefined;
    }
    let aboveBlockButton;
    let belowBlockButton;
    if (this.showAbove()) {
      aboveBlockButton = this.createBlockButton(
        ContextButtonType.BLOCK_ABOVE,
        this.group.lineRange.right.start_line - 1
      );
    }
    if (this.showBelow()) {
      belowBlockButton = this.createBlockButton(
        ContextButtonType.BLOCK_BELOW,
        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 ? false : true;
    return {
      title: tooltipText,
      positionBelow: position,
    };
  }

  /**
   * Creates a "expand until end of block" button. This is based on syntax tree
   * information for the *right* side of the diff.
   */
  private createBlockButton(
    buttonType: ContextButtonType,
    referenceLineRight: number
  ) {
    if (this.syntaxTreeRight === undefined) return;
    const outlineSyntaxPath = findBlockTreePathForLine(
      referenceLineRight,
      this.syntaxTreeRight
    );
    let linesToExpand = this.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 - referenceLineRight);
      if (distanceToTargetLine < this.numLines()) {
        linesToExpand = distanceToTargetLine;
      }
    }
    const tooltip = this.createBlockButtonTooltip(
      buttonType,
      outlineSyntaxPath,
      linesToExpand
    );
    return this.createContextButton(buttonType, linesToExpand, tooltip);
  }

  override render() {
    if (!this.group) return nothing;
    return html`
      <div class="horizontalFlex">
        ${this.createExpandAllButtonContainer()}
        ${this.createPartialExpansionButtons()}
        ${this.createBlockExpansionButtons()}
      </div>
    `;
  }
}

customElements.define('gr-context-controls', GrContextControls);

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