/**
 * @license
 * Copyright 2021 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import './gr-related-change';
import './gr-related-collapse';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import '../../plugins/gr-endpoint-param/gr-endpoint-param';
import '../../plugins/gr-endpoint-slot/gr-endpoint-slot';
import '../../shared/gr-icon/gr-icon';
import {classMap} from 'lit/directives/class-map.js';
import {LitElement, css, html, TemplateResult} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
import {sharedStyles} from '../../../styles/shared-styles';
import {
  ChangeInfo,
  CommitId,
  PatchSetNum,
  RelatedChangeAndCommitInfo,
  RelatedChangesInfo,
  RevisionPatchSetNum,
  SubmittedTogetherInfo,
} from '../../../types/common';
import {getAppContext} from '../../../services/app-context';
import {ParsedChangeInfo} from '../../../types/types';
import {truncatePath} from '../../../utils/path-list-util';
import {pluralize} from '../../../utils/string-util';
import {
  changeIsOpen,
  getRevisionKey,
  isChangeInfo,
} from '../../../utils/change-util';
import {DEFALT_NUM_CHANGES_WHEN_COLLAPSED} from './gr-related-collapse';
import {createChangeUrl} from '../../../models/views/change';

export interface ChangeMarkersInList {
  showCurrentChangeArrow: boolean;
  showWhenCollapsed: boolean;
  showTopArrow: boolean;
  showBottomArrow: boolean;
}

export enum Section {
  RELATED_CHANGES = 'related changes',
  SUBMITTED_TOGETHER = 'submitted together',
  SAME_TOPIC = 'same topic',
  MERGE_CONFLICTS = 'merge conflicts',
  CHERRY_PICKS = 'cherry picks',
}

@customElement('gr-related-changes-list')
export class GrRelatedChangesList extends LitElement {
  @property({type: Object})
  change?: ParsedChangeInfo;

  @property({type: String})
  patchNum?: PatchSetNum;

  @property({type: Boolean})
  mergeable?: boolean;

  @state()
  submittedTogether?: SubmittedTogetherInfo = {
    changes: [],
    non_visible_changes: 0,
  };

  @state()
  relatedChanges: RelatedChangeAndCommitInfo[] = [];

  @state()
  conflictingChanges: ChangeInfo[] = [];

  @state()
  cherryPickChanges: ChangeInfo[] = [];

  @state()
  sameTopicChanges: ChangeInfo[] = [];

  private readonly restApiService = getAppContext().restApiService;

  static override get styles() {
    return [
      sharedStyles,
      css`
        .note {
          color: var(--error-text-color);
          margin-left: 1.2em;
        }
        section {
          margin-bottom: var(--spacing-l);
        }
        .relatedChangeLine {
          display: flex;
          visibility: visible;
          height: auto;
        }
        .marker.arrow {
          visibility: hidden;
          min-width: 20px;
        }
        .marker.arrowToCurrentChange {
          min-width: 20px;
          text-align: center;
        }
        .marker.space {
          height: 1px;
          min-width: 20px;
        }
        .repo,
        .branch {
          color: var(--primary-text-color);
        }
        @media screen and (max-width: 1400px) {
          .repo,
          .branch {
            display: none;
          }
        }

        gr-related-collapse[collapsed] .marker.arrow {
          visibility: visible;
          min-width: auto;
        }
        gr-related-collapse[collapsed] .relatedChangeLine.show-when-collapsed {
          visibility: visible;
          height: auto;
        }
        /* keep width, so width of section and position of show all button
         * are set according to width of all (even hidden) elements
         */
        gr-related-collapse[collapsed] .relatedChangeLine {
          visibility: hidden;
          height: 0px;
        }
      `,
    ];
  }

  override render() {
    const sectionSize = this.sectionSizeFactory(
      this.relatedChanges.length,
      this.submittedTogether?.changes.length || 0,
      this.sameTopicChanges.length,
      this.conflictingChanges.length,
      this.cherryPickChanges.length
    );

    const sectionRenderers = [
      this.renderRelationChain,
      this.renderSubmittedTogether,
      this.renderSameTopic,
      this.renderMergeConflicts,
      this.renderCherryPicks,
    ];

    let firstNonEmptySectionFound = false;
    const sections = [];
    for (const renderer of sectionRenderers) {
      const section: TemplateResult<1> | undefined = renderer.call(
        this,
        !firstNonEmptySectionFound,
        sectionSize
      );
      firstNonEmptySectionFound = firstNonEmptySectionFound || !!section;
      sections.push(section);
    }

    return html`<gr-endpoint-decorator name="related-changes-section">
      <gr-endpoint-param
        name="change"
        .value=${this.change}
      ></gr-endpoint-param>
      <gr-endpoint-slot name="top"></gr-endpoint-slot>
      ${sections}
      <gr-endpoint-slot name="bottom"></gr-endpoint-slot>
    </gr-endpoint-decorator>`;
  }

  private renderRelationChain(
    isFirst: boolean,
    sectionSize: (section: Section) => number
  ) {
    if (this.relatedChanges.length === 0) {
      return undefined;
    }
    const relatedChangesMarkersPredicate = this.markersPredicateFactory(
      this.relatedChanges.length,
      this.relatedChanges.findIndex(relatedChange =>
        this._changesEqual(relatedChange, this.change)
      ),
      sectionSize(Section.RELATED_CHANGES)
    );
    const connectedRevisions = this._computeConnectedRevisions(
      this.change,
      this.patchNum,
      this.relatedChanges
    );

    return html`<section id="relatedChanges">
      <gr-related-collapse
        title="Relation chain"
        class=${classMap({first: isFirst})}
        .length=${this.relatedChanges.length}
        .numChangesWhenCollapsed=${sectionSize(Section.RELATED_CHANGES)}
      >
        ${this.relatedChanges.map(
          (change, index) =>
            html`<div
              class=${classMap({
                ['relatedChangeLine']: true,
                ['show-when-collapsed']:
                  relatedChangesMarkersPredicate(index).showWhenCollapsed,
              })}
            >
              ${this.renderMarkers(
                relatedChangesMarkersPredicate(index)
              )}<gr-related-change
                .change=${change}
                .connectedRevisions=${connectedRevisions}
                .href=${change?._change_number
                  ? createChangeUrl({
                      changeNum: change._change_number,
                      project: change.project,
                      usp: 'related-change',
                      patchNum: change._revision_number as RevisionPatchSetNum,
                    })
                  : ''}
                show-change-status
                show-submittable-check
                >${change.commit.subject}</gr-related-change
              >
            </div>`
        )}
      </gr-related-collapse>
    </section>`;
  }

  private renderSubmittedTogether(
    isFirst: boolean,
    sectionSize: (section: Section) => number
  ) {
    const submittedTogetherChanges = this.submittedTogether?.changes ?? [];
    if (
      !submittedTogetherChanges.length &&
      !this.submittedTogether?.non_visible_changes
    ) {
      return undefined;
    }
    const countNonVisibleChanges =
      this.submittedTogether?.non_visible_changes ?? 0;
    const submittedTogetherMarkersPredicate = this.markersPredicateFactory(
      submittedTogetherChanges.length,
      submittedTogetherChanges.findIndex(relatedChange =>
        this._changesEqual(relatedChange, this.change)
      ),
      sectionSize(Section.SUBMITTED_TOGETHER)
    );
    return html`<section id="submittedTogether">
      <gr-related-collapse
        title="Submitted together"
        class=${classMap({first: isFirst})}
        .length=${submittedTogetherChanges.length}
        .numChangesWhenCollapsed=${sectionSize(Section.SUBMITTED_TOGETHER)}
      >
        ${submittedTogetherChanges.map(
          (change, index) =>
            html`<div
              class=${classMap({
                ['relatedChangeLine']: true,
                ['show-when-collapsed']:
                  submittedTogetherMarkersPredicate(index).showWhenCollapsed,
              })}
            >
              ${this.renderMarkers(
                submittedTogetherMarkersPredicate(index)
              )}${this.renderSubmittedTogetherLine(change, true)}
            </div>`
        )}
      </gr-related-collapse>
      <div class="note" ?hidden=${!countNonVisibleChanges}>
        (+ ${pluralize(countNonVisibleChanges, 'non-visible change')})
      </div>
    </section>`;
  }

  private renderSubmittedTogetherLine(
    change: ChangeInfo,
    showSubmittabilityCheck: boolean
  ) {
    const truncatedRepo = truncatePath(change.project, 2);
    return html`
      <span class="repo" .title=${change.project}>${truncatedRepo}</span
      ><span class="branch">&nbsp;|&nbsp;${change.branch}&nbsp;</span>
      <gr-related-change
        .label=${this.renderChangeTitle(change)}
        .change=${change}
        .href=${createChangeUrl({change, usp: 'submitted-together'})}
        ?show-submittable-check=${showSubmittabilityCheck}
        >${change.subject}</gr-related-change
      >
    `;
  }

  private renderSameTopic(
    isFirst: boolean,
    sectionSize: (section: Section) => number
  ) {
    if (!this.sameTopicChanges?.length) {
      return undefined;
    }

    const sameTopicMarkersPredicate = this.markersPredicateFactory(
      this.sameTopicChanges.length,
      -1,
      sectionSize(Section.SAME_TOPIC)
    );
    return html`<section id="sameTopic">
      <gr-related-collapse
        title="Same topic"
        class=${classMap({first: isFirst})}
        .length=${this.sameTopicChanges.length}
        .numChangesWhenCollapsed=${sectionSize(Section.SAME_TOPIC)}
      >
        ${this.sameTopicChanges.map(
          (change, index) =>
            html`<div
              class=${classMap({
                ['relatedChangeLine']: true,
                ['show-when-collapsed']:
                  sameTopicMarkersPredicate(index).showWhenCollapsed,
              })}
            >
              ${this.renderMarkers(
                sameTopicMarkersPredicate(index)
              )}${this.renderSubmittedTogetherLine(change, false)}
            </div>`
        )}
      </gr-related-collapse>
    </section>`;
  }

  private renderMergeConflicts(
    isFirst: boolean,
    sectionSize: (section: Section) => number
  ) {
    if (!this.conflictingChanges?.length) {
      return undefined;
    }
    const mergeConflictsMarkersPredicate = this.markersPredicateFactory(
      this.conflictingChanges.length,
      -1,
      sectionSize(Section.MERGE_CONFLICTS)
    );
    return html`<section id="mergeConflicts">
      <gr-related-collapse
        title="Merge conflicts"
        class=${classMap({first: isFirst})}
        .length=${this.conflictingChanges.length}
        .numChangesWhenCollapsed=${sectionSize(Section.MERGE_CONFLICTS)}
      >
        ${this.conflictingChanges.map(
          (change, index) =>
            html`<div
              class=${classMap({
                ['relatedChangeLine']: true,
                ['show-when-collapsed']:
                  mergeConflictsMarkersPredicate(index).showWhenCollapsed,
              })}
            >
              ${this.renderMarkers(
                mergeConflictsMarkersPredicate(index)
              )}<gr-related-change
                .change=${change}
                .href=${createChangeUrl({change, usp: 'merge-conflict'})}
                >${change.subject}</gr-related-change
              >
            </div>`
        )}
      </gr-related-collapse>
    </section>`;
  }

  private renderCherryPicks(
    isFirst: boolean,
    sectionSize: (section: Section) => number
  ) {
    if (!this.cherryPickChanges.length) {
      return undefined;
    }
    const cherryPicksMarkersPredicate = this.markersPredicateFactory(
      this.cherryPickChanges.length,
      -1,
      sectionSize(Section.CHERRY_PICKS)
    );
    return html`<section id="cherryPicks">
      <gr-related-collapse
        title="Cherry picks"
        class=${classMap({first: isFirst})}
        .length=${this.cherryPickChanges.length}
        .numChangesWhenCollapsed=${sectionSize(Section.CHERRY_PICKS)}
      >
        ${this.cherryPickChanges.map(
          (change, index) =>
            html`<div
              class=${classMap({
                ['relatedChangeLine']: true,
                ['show-when-collapsed']:
                  cherryPicksMarkersPredicate(index).showWhenCollapsed,
              })}
            >
              ${this.renderMarkers(
                cherryPicksMarkersPredicate(index)
              )}<gr-related-change
                .change=${change}
                .href=${createChangeUrl({change, usp: 'cherry-pick'})}
                >${change.branch}: ${change.subject}</gr-related-change
              >
            </div>`
        )}
      </gr-related-collapse>
    </section>`;
  }

  private renderChangeTitle(change: ChangeInfo) {
    return `${change.project}: ${change.branch}: ${change.subject}`;
  }

  sectionSizeFactory(
    relatedChangesLen: number,
    submittedTogetherLen: number,
    sameTopicLen: number,
    mergeConflictsLen: number,
    cherryPicksLen: number
  ) {
    const calcDefaultSize = (length: number) =>
      Math.min(length, DEFALT_NUM_CHANGES_WHEN_COLLAPSED);

    const sectionSizes = [
      {
        section: Section.RELATED_CHANGES,
        size: calcDefaultSize(relatedChangesLen),
        len: relatedChangesLen,
      },
      {
        section: Section.SUBMITTED_TOGETHER,
        size: calcDefaultSize(submittedTogetherLen),
        len: submittedTogetherLen,
      },
      {
        section: Section.SAME_TOPIC,
        size: calcDefaultSize(sameTopicLen),
        len: sameTopicLen,
      },
      {
        section: Section.MERGE_CONFLICTS,
        size: calcDefaultSize(mergeConflictsLen),
        len: mergeConflictsLen,
      },
      {
        section: Section.CHERRY_PICKS,
        size: calcDefaultSize(cherryPicksLen),
        len: cherryPicksLen,
      },
    ];

    const FILLER = 1; // space for header
    let totalSize = sectionSizes.reduce(
      (acc, val) => acc + val.size + (val.size !== 0 ? FILLER : 0),
      0
    );

    const MAX_SIZE = 16;
    for (let i = 0; i < sectionSizes.length; i++) {
      if (totalSize >= MAX_SIZE) break;
      const sizeObj = sectionSizes[i];
      if (sizeObj.size === sizeObj.len) continue;
      const newSize = Math.min(
        MAX_SIZE - totalSize + sizeObj.size,
        sizeObj.len
      );
      totalSize += newSize - sizeObj.size;
      sizeObj.size = newSize;
    }

    return (section: Section) => {
      const sizeObj = sectionSizes.find(sizeObj => sizeObj.section === section);
      if (sizeObj) return sizeObj.size;
      return DEFALT_NUM_CHANGES_WHEN_COLLAPSED;
    };
  }

  markersPredicateFactory(
    length: number,
    highlightIndex: number,
    numChangesShownWhenCollapsed = DEFALT_NUM_CHANGES_WHEN_COLLAPSED
  ): (index: number) => ChangeMarkersInList {
    const showWhenCollapsedPredicate = (index: number) => {
      if (highlightIndex === -1) return index < numChangesShownWhenCollapsed;
      if (highlightIndex === 0)
        return index <= numChangesShownWhenCollapsed - 1;
      if (highlightIndex === length - 1)
        return index >= length - numChangesShownWhenCollapsed;
      let numBeforeHighlight = Math.floor(numChangesShownWhenCollapsed / 2);
      let numAfterHighlight =
        Math.floor(numChangesShownWhenCollapsed / 2) -
        (numChangesShownWhenCollapsed % 2 ? 0 : 1);
      numBeforeHighlight += Math.max(
        highlightIndex + numAfterHighlight - length + 1,
        0
      );
      numAfterHighlight -= Math.min(0, highlightIndex - numBeforeHighlight);
      return (
        highlightIndex - numBeforeHighlight <= index &&
        index <= highlightIndex + numAfterHighlight
      );
    };
    return (index: number) => {
      return {
        showCurrentChangeArrow:
          highlightIndex !== -1 && index === highlightIndex,
        showWhenCollapsed: showWhenCollapsedPredicate(index),
        showTopArrow:
          index >= 1 &&
          index !== highlightIndex &&
          showWhenCollapsedPredicate(index) &&
          !showWhenCollapsedPredicate(index - 1),
        showBottomArrow:
          index <= length - 2 &&
          index !== highlightIndex &&
          showWhenCollapsedPredicate(index) &&
          !showWhenCollapsedPredicate(index + 1),
      };
    };
  }

  renderMarkers(changeMarkers: ChangeMarkersInList) {
    if (changeMarkers.showCurrentChangeArrow) {
      return html`<span
        role="img"
        class="marker arrowToCurrentChange"
        aria-label="Arrow marking current change"
        >➔</span
      >`;
    }
    if (changeMarkers.showTopArrow) {
      return html`<span
        role="img"
        class="marker arrow"
        aria-label="Arrow marking change has collapsed ancestors"
        ><gr-icon icon="arrow_drop_up"></gr-icon
      ></span> `;
    }
    if (changeMarkers.showBottomArrow) {
      return html`<span
        role="img"
        class="marker arrow"
        aria-label="Arrow marking change has collapsed descendants"
        ><gr-icon icon="arrow_drop_down"></gr-icon
      ></span> `;
    }
    return html`<span class="marker space"></span>`;
  }

  reload(getRelatedChanges?: Promise<RelatedChangesInfo | undefined>) {
    const change = this.change;
    if (!change) return Promise.reject(new Error('change missing'));
    if (!this.patchNum) return Promise.reject(new Error('patchNum missing'));
    if (!getRelatedChanges) {
      getRelatedChanges = this.restApiService.getRelatedChanges(
        change._number,
        this.patchNum
      );
    }
    const promises: Array<Promise<void>> = [
      getRelatedChanges.then(response => {
        if (!response) {
          throw new Error('getRelatedChanges returned undefined response');
        }
        this.relatedChanges = response?.changes ?? [];
      }),
      this.restApiService
        .getChangesSubmittedTogether(change._number)
        .then(response => {
          this.submittedTogether = response;
        }),
      this.restApiService
        .getChangeCherryPicks(change.project, change.change_id, change._number)
        .then(response => {
          this.cherryPickChanges = response || [];
        }),
    ];

    // Get conflicts if change is open and is mergeable.
    // Mergeable is output of restApiServict.getMergeable from gr-change-view
    if (changeIsOpen(change) && this.mergeable) {
      promises.push(
        this.restApiService
          .getChangeConflicts(change._number)
          .then(response => {
            this.conflictingChanges = response ?? [];
          })
      );
    }
    if (change.topic) {
      const changeTopic = change.topic;
      promises.push(
        this.restApiService.getConfig().then(config => {
          if (config && !config.change.submit_whole_topic) {
            return this.restApiService
              .getChangesWithSameTopic(changeTopic, {
                openChangesOnly: true,
                changeToExclude: change._number,
              })
              .then(response => {
                if (changeTopic === this.change?.topic) {
                  this.sameTopicChanges = response ?? [];
                }
              });
          }
          this.sameTopicChanges = [];
          return Promise.resolve();
        })
      );
    }

    return Promise.all(promises);
  }

  /**
   * Do the given objects describe the same change? Compares the changes by
   * their numbers.
   */
  _changesEqual(
    a?: ChangeInfo | RelatedChangeAndCommitInfo,
    b?: ChangeInfo | ParsedChangeInfo | RelatedChangeAndCommitInfo
  ) {
    const aNum = this._getChangeNumber(a);
    const bNum = this._getChangeNumber(b);
    return aNum === bNum;
  }

  /**
   * Get the change number from either a ChangeInfo (such as those included in
   * SubmittedTogetherInfo responses) or get the change number from a
   * RelatedChangeAndCommitInfo (such as those included in a
   * RelatedChangesInfo response).
   */
  _getChangeNumber(
    change?: ChangeInfo | ParsedChangeInfo | RelatedChangeAndCommitInfo
  ) {
    // Default to 0 if change property is not defined.
    if (!change) return 0;

    if (isChangeInfo(change)) {
      return change._number;
    }
    return change._change_number;
  }

  /*
   * A list of commit ids connected to change to understand if other change
   * is direct or indirect ancestor / descendant.
   */
  _computeConnectedRevisions(
    change?: ParsedChangeInfo,
    patchNum?: PatchSetNum,
    relatedChanges?: RelatedChangeAndCommitInfo[]
  ) {
    if (!patchNum || !relatedChanges || !change) {
      return [];
    }

    const connected: CommitId[] = [];
    const changeRevision = getRevisionKey(change, patchNum);
    const commits = relatedChanges.map(c => c.commit);
    let pos = commits.length - 1;

    while (pos >= 0) {
      const commit: CommitId = commits[pos].commit;
      connected.push(commit);
      // TODO(TS): Ensure that both (commit and changeRevision) are string and use === instead
      // eslint-disable-next-line eqeqeq
      if (commit == changeRevision) {
        break;
      }
      pos--;
    }
    while (pos >= 0) {
      for (let i = 0; i < commits[pos].parents.length; i++) {
        if (connected.includes(commits[pos].parents[i].commit)) {
          connected.push(commits[pos].commit);
          break;
        }
      }
      --pos;
    }
    return connected;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-related-changes-list': GrRelatedChangesList;
  }
}
