/**
 * @license
 * Copyright (C) 2020 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 {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {getPluginLoader} from './gr-plugin-loader';
import {patchNumEquals} from '../../../utils/patch-set-util';
import {customElement} from '@polymer/decorators';
import {
  ChangeInfo,
  LabelNameToValuesMap,
  RevisionInfo,
} from '../../../types/common';
import {GrAnnotationActionsInterface} from './gr-annotation-actions-js-api';
import {GrAdminApi, MenuLink} from '../../plugins/gr-admin-api/gr-admin-api';
import {
  JsApiService,
  EventCallback,
  ShowChangeDetail,
  ShowRevisionActionsDetail,
} from './gr-js-api-types';
import {EventType, TargetElement} from '../../plugins/gr-plugin-types';
import {DiffLayer, HighlightJS} from '../../../types/types';
import {ParsedChangeInfo} from '../gr-rest-api-interface/gr-reviewer-updates-parser';
import {appContext} from '../../../services/app-context';

const elements: {[key: string]: HTMLElement} = {};
const eventCallbacks: {[key: string]: EventCallback[]} = {};

@customElement('gr-js-api-interface')
export class GrJsApiInterface
  extends GestureEventListeners(LegacyElementMixin(PolymerElement))
  implements JsApiService {
  private readonly reporting = appContext.reportingService;

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  handleEvent(type: EventType, detail: any) {
    getPluginLoader()
      .awaitPluginsLoaded()
      .then(() => {
        switch (type) {
          case EventType.HISTORY:
            this._handleHistory(detail);
            break;
          case EventType.SHOW_CHANGE:
            this._handleShowChange(detail);
            break;
          case EventType.COMMENT:
            this._handleComment(detail);
            break;
          case EventType.LABEL_CHANGE:
            this._handleLabelChange(detail);
            break;
          case EventType.SHOW_REVISION_ACTIONS:
            this._handleShowRevisionActions(detail);
            break;
          case EventType.HIGHLIGHTJS_LOADED:
            this._handleHighlightjsLoaded(detail);
            break;
          default:
            console.warn(
              'handleEvent called with unsupported event type:',
              type
            );
            break;
        }
      });
  }

  addElement(key: TargetElement, el: HTMLElement) {
    elements[key] = el;
  }

  getElement(key: TargetElement) {
    return elements[key];
  }

  addEventCallback(eventName: EventType, callback: EventCallback) {
    if (!eventCallbacks[eventName]) {
      eventCallbacks[eventName] = [];
    }
    eventCallbacks[eventName].push(callback);
  }

  canSubmitChange(change: ChangeInfo, revision?: RevisionInfo | null) {
    const submitCallbacks = this._getEventCallbacks(EventType.SUBMIT_CHANGE);
    const cancelSubmit = submitCallbacks.some(callback => {
      try {
        return callback(change, revision) === false;
      } catch (err) {
        this.reporting.error(err);
      }
      return false;
    });

    return !cancelSubmit;
  }

  /** For testing only. */
  _removeEventCallbacks() {
    for (const type of Object.values(EventType)) {
      eventCallbacks[type] = [];
    }
  }

  // TODO(TS): The HISTORY event and its handler seem unused.
  _handleHistory(detail: {path: string}) {
    for (const cb of this._getEventCallbacks(EventType.HISTORY)) {
      try {
        cb(detail.path);
      } catch (err) {
        this.reporting.error(err);
      }
    }
  }

  _handleShowChange(detail: ShowChangeDetail) {
    // Note (issue 8221) Shallow clone the change object and add a mergeable
    // getter with deprecation warning. This makes the change detail appear as
    // though SKIP_MERGEABLE was not set, so that plugins that expect it can
    // still access.
    //
    // This clone and getter can be removed after plugins migrate to use
    // info.mergeable.
    //
    // assign on getter with existing property will report error
    // see Issue: 12286
    const change = {
      ...detail.change,
      get mergeable() {
        console.warn(
          'Accessing change.mergeable from SHOW_CHANGE is ' +
            'deprecated! Use info.mergeable instead.'
        );
        return detail.info && detail.info.mergeable;
      },
    };
    const patchNum = detail.patchNum;
    const info = detail.info;

    let revision;
    for (const rev of Object.values(change.revisions || {})) {
      if (patchNumEquals(rev._number, patchNum)) {
        revision = rev;
        break;
      }
    }

    for (const cb of this._getEventCallbacks(EventType.SHOW_CHANGE)) {
      try {
        cb(change, revision, info);
      } catch (err) {
        this.reporting.error(err);
      }
    }
  }

  _handleShowRevisionActions(detail: ShowRevisionActionsDetail) {
    const registeredCallbacks = this._getEventCallbacks(
      EventType.SHOW_REVISION_ACTIONS
    );
    for (const cb of registeredCallbacks) {
      try {
        cb(detail.revisionActions, detail.change);
      } catch (err) {
        this.reporting.error(err);
      }
    }
  }

  handleCommitMessage(change: ChangeInfo | ParsedChangeInfo, msg: string) {
    for (const cb of this._getEventCallbacks(EventType.COMMIT_MSG_EDIT)) {
      try {
        cb(change, msg);
      } catch (err) {
        this.reporting.error(err);
      }
    }
  }

  // TODO(TS): The COMMENT event and its handler seem unused.
  _handleComment(detail: {node: Node}) {
    for (const cb of this._getEventCallbacks(EventType.COMMENT)) {
      try {
        cb(detail.node);
      } catch (err) {
        this.reporting.error(err);
      }
    }
  }

  _handleLabelChange(detail: {change: ChangeInfo}) {
    for (const cb of this._getEventCallbacks(EventType.LABEL_CHANGE)) {
      try {
        cb(detail.change);
      } catch (err) {
        this.reporting.error(err);
      }
    }
  }

  _handleHighlightjsLoaded(detail: {hljs: HighlightJS}) {
    for (const cb of this._getEventCallbacks(EventType.HIGHLIGHTJS_LOADED)) {
      try {
        cb(detail.hljs);
      } catch (err) {
        this.reporting.error(err);
      }
    }
  }

  modifyRevertMsg(change: ChangeInfo, revertMsg: string, origMsg: string) {
    for (const cb of this._getEventCallbacks(EventType.REVERT)) {
      try {
        revertMsg = cb(change, revertMsg, origMsg) as string;
      } catch (err) {
        this.reporting.error(err);
      }
    }
    return revertMsg;
  }

  modifyRevertSubmissionMsg(
    change: ChangeInfo,
    revertSubmissionMsg: string,
    origMsg: string
  ) {
    for (const cb of this._getEventCallbacks(EventType.REVERT_SUBMISSION)) {
      try {
        revertSubmissionMsg = cb(
          change,
          revertSubmissionMsg,
          origMsg
        ) as string;
      } catch (err) {
        this.reporting.error(err);
      }
    }
    return revertSubmissionMsg;
  }

  getDiffLayers(path: string, changeNum: number) {
    const layers: DiffLayer[] = [];
    for (const cb of this._getEventCallbacks(EventType.ANNOTATE_DIFF)) {
      const annotationApi = (cb as unknown) as GrAnnotationActionsInterface;
      try {
        const layer = annotationApi.getLayer(path, changeNum);
        layers.push(layer);
      } catch (err) {
        this.reporting.error(err);
      }
    }
    return layers;
  }

  disposeDiffLayers(path: string) {
    for (const cb of this._getEventCallbacks(EventType.ANNOTATE_DIFF)) {
      try {
        const annotationApi = (cb as unknown) as GrAnnotationActionsInterface;
        annotationApi.disposeLayer(path);
      } catch (err) {
        this.reporting.error(err);
      }
    }
  }

  /**
   * Retrieves coverage data possibly provided by a plugin.
   *
   * Will wait for plugins to be loaded. If multiple plugins offer a coverage
   * provider, the first one is returned. If no plugin offers a coverage provider,
   * will resolve to null.
   */
  getCoverageAnnotationApis(): Promise<GrAnnotationActionsInterface[]> {
    return getPluginLoader()
      .awaitPluginsLoaded()
      .then(() => {
        const providers: GrAnnotationActionsInterface[] = [];
        this._getEventCallbacks(EventType.ANNOTATE_DIFF).forEach(cb => {
          const annotationApi = (cb as unknown) as GrAnnotationActionsInterface;
          const provider = annotationApi.getCoverageProvider();
          if (provider) providers.push(annotationApi);
        });
        return providers;
      });
  }

  getAdminMenuLinks(): MenuLink[] {
    const links: MenuLink[] = [];
    for (const cb of this._getEventCallbacks(EventType.ADMIN_MENU_LINKS)) {
      const adminApi = (cb as unknown) as GrAdminApi;
      links.push(...adminApi.getMenuLinks());
    }
    return links;
  }

  getLabelValuesPostRevert(change?: ChangeInfo): LabelNameToValuesMap {
    let labels: LabelNameToValuesMap = {};
    for (const cb of this._getEventCallbacks(EventType.POST_REVERT)) {
      try {
        labels = cb(change);
      } catch (err) {
        this.reporting.error(err);
      }
    }
    return labels;
  }

  _getEventCallbacks(type: EventType) {
    return eventCallbacks[type] || [];
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-js-api-interface': JsApiService & Element;
  }
}
