/**
 * @license
 * Copyright (C) 2016 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 to get Gerrit interface */
/* TODO(taoalpha): decouple gr-gerrit from gr-js-api-interface */
import '../gr-error-dialog/gr-error-dialog';
import '../../shared/gr-alert/gr-alert';
import '../../shared/gr-overlay/gr-overlay';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface';
import '../../shared/gr-js-api-interface/gr-js-api-interface';
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 {htmlTemplate} from './gr-error-manager_html';
import {getBaseUrl} from '../../../utils/url-util';
import {appContext} from '../../../services/app-context';
import {IronA11yAnnouncer} from '@polymer/iron-a11y-announcer/iron-a11y-announcer';
import {customElement, property} from '@polymer/decorators';
import {ReportingService} from '../../../services/gr-reporting/gr-reporting';
import {AuthService} from '../../../services/gr-auth/gr-auth';
import {EventEmitterService} from '../../../services/gr-event-interface/gr-event-interface';
import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
import {GrErrorDialog} from '../gr-error-dialog/gr-error-dialog';
import {GrAlert} from '../../shared/gr-alert/gr-alert';
import {RestApiService} from '../../../services/services/gr-rest-api/gr-rest-api';
import {FetchRequest} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {ErrorType, FixIronA11yAnnouncer} from '../../../types/types';
import {AccountId} from '../../../types/common';
import {EventType} from '../../../utils/event-util';

const HIDE_ALERT_TIMEOUT_MS = 5000;
const CHECK_SIGN_IN_INTERVAL_MS = 60 * 1000;
const STALE_CREDENTIAL_THRESHOLD_MS = 10 * 60 * 1000;
const SIGN_IN_WIDTH_PX = 690;
const SIGN_IN_HEIGHT_PX = 500;
const TOO_MANY_FILES = 'too many files to find conflicts';
const AUTHENTICATION_REQUIRED = 'Authentication required\n';

// Bigger number has higher priority
const ErrorTypePriority = {
  [ErrorType.AUTH]: 3,
  [ErrorType.NETWORK]: 2,
  [ErrorType.GENERIC]: 1,
};

interface ErrorMsg {
  errorText?: string;
  status?: number;
  statusText?: string;
  url?: string;
  trace?: string | null;
  tip?: string;
}

export const __testOnly_ErrorType = ErrorType;

export interface GrErrorManager {
  $: {
    noInteractionOverlay: GrOverlay;
    errorDialog: GrErrorDialog;
    errorOverlay: GrOverlay;
    restAPI: RestApiService & Element;
  };
}
@customElement('gr-error-manager')
export class GrErrorManager extends GestureEventListeners(
  LegacyElementMixin(PolymerElement)
) {
  static get template() {
    return htmlTemplate;
  }

  /**
   * The ID of the account that was logged in when the app was launched. If
   * not set, then there was no account at launch.
   */
  @property({type: Number})
  knownAccountId?: AccountId | null;

  @property({type: Object})
  _alertElement: GrAlert | null = null;

  @property({type: Number})
  _hideAlertHandle: number | null = null;

  @property({type: Boolean})
  _refreshingCredentials = false;

  /**
   * The time (in milliseconds) since the most recent credential check.
   */
  @property({type: Number})
  _lastCredentialCheck: number = Date.now();

  @property({type: String})
  loginUrl = '/login';

  reporting: ReportingService;

  _authService: AuthService;

  eventEmitter: EventEmitterService;

  _authErrorHandlerDeregistrationHook?: Function;

  constructor() {
    super();

    this._authService = appContext.authService;

    this.reporting = appContext.reportingService;
    this.eventEmitter = appContext.eventEmitter;
  }

  /** @override */
  attached() {
    super.attached();
    this.listen(document, 'server-error', '_handleServerError');
    this.listen(document, 'network-error', '_handleNetworkError');
    this.listen(document, EventType.SHOW_ALERT, '_handleShowAlert');
    this.listen(document, 'hide-alert', '_hideAlert');
    this.listen(document, 'show-error', '_handleShowErrorDialog');
    this.listen(document, 'visibilitychange', '_handleVisibilityChange');
    this.listen(document, 'show-auth-required', '_handleAuthRequired');

    this._authErrorHandlerDeregistrationHook = this.eventEmitter.on(
      'auth-error',
      event => {
        this._handleAuthError(event.message, event.action);
      }
    );

    ((IronA11yAnnouncer as unknown) as FixIronA11yAnnouncer).requestAvailability();
  }

  /** @override */
  detached() {
    super.detached();
    this._clearHideAlertHandle();
    this.unlisten(document, 'server-error', '_handleServerError');
    this.unlisten(document, 'network-error', '_handleNetworkError');
    this.unlisten(document, EventType.SHOW_ALERT, '_handleShowAlert');
    this.unlisten(document, 'hide-alert', '_hideAlert');
    this.unlisten(document, 'show-error', '_handleShowErrorDialog');
    this.unlisten(document, 'visibilitychange', '_handleVisibilityChange');
    this.unlisten(document, 'show-auth-required', '_handleAuthRequired');

    if (this._authErrorHandlerDeregistrationHook) {
      this._authErrorHandlerDeregistrationHook();
    }
  }

  _shouldSuppressError(msg: string) {
    return msg.includes(TOO_MANY_FILES);
  }

  _handleAuthRequired() {
    this._showAuthErrorAlert(
      'Log in is required to perform that action.',
      'Log in.'
    );
  }

  _handleAuthError(msg: string, action: string) {
    this.$.noInteractionOverlay.open().then(() => {
      this._showAuthErrorAlert(msg, action);
    });
  }

  _handleServerError(
    e: CustomEvent<{response: Response; request: FetchRequest}>
  ) {
    const {request, response} = e.detail;
    response.text().then(errorText => {
      const url = request && (request.anonymizedUrl || request.url);
      const {status, statusText} = response;
      if (
        response.status === 403 &&
        !this._authService.isAuthed &&
        errorText === AUTHENTICATION_REQUIRED
      ) {
        // if not authed previously, this is trying to access auth required APIs
        // show auth required alert
        this._handleAuthRequired();
      } else if (
        response.status === 403 &&
        this._authService.isAuthed &&
        errorText === AUTHENTICATION_REQUIRED
      ) {
        // The app was logged at one point and is now getting auth errors.
        // This indicates the auth token may no longer valid.
        // Re-check on auth
        this._authService.clearCache();
        this.$.restAPI.getLoggedIn();
      } else if (!this._shouldSuppressError(errorText)) {
        const trace =
          response.headers && response.headers.get('X-Gerrit-Trace');
        if (response.status === 404) {
          this._showNotFoundMessageWithTip({
            status,
            statusText,
            errorText,
            url,
            trace,
          });
        } else {
          this._showErrorDialog(
            this._constructServerErrorMsg({
              status,
              statusText,
              errorText,
              url,
              trace,
            })
          );
        }
      }
      console.info(`server error: ${errorText}`);
    });
  }

  _showNotFoundMessageWithTip({
    status,
    statusText,
    errorText,
    url,
    trace,
  }: ErrorMsg) {
    this.$.restAPI.getLoggedIn().then(isLoggedIn => {
      const tip = isLoggedIn
        ? 'You might have not enough privileges.'
        : 'You might have not enough privileges. Sign in and try again.';
      this._showErrorDialog(
        this._constructServerErrorMsg({
          status,
          statusText,
          errorText,
          url,
          trace,
          tip,
        }),
        {
          showSignInButton: !isLoggedIn,
        }
      );
    });
  }

  _constructServerErrorMsg({
    errorText,
    status,
    statusText,
    url,
    trace,
    tip,
  }: ErrorMsg) {
    let err = '';
    if (tip) {
      err += `${tip}\n\n`;
    }
    err += `Error ${status}`;
    if (statusText) {
      err += ` (${statusText})`;
    }
    if (errorText || url) {
      err += ': ';
    }
    if (errorText) {
      err += errorText;
    }
    if (url) {
      err += `\nEndpoint: ${url}`;
    }
    if (trace) {
      err += `\nTrace Id: ${trace}`;
    }
    return err;
  }

  _handleShowAlert(e: CustomEvent) {
    this._showAlert(
      e.detail.message,
      e.detail.action,
      e.detail.callback,
      e.detail.dismissOnNavigation
    );
  }

  _handleNetworkError(e: CustomEvent) {
    this._showAlert('Server unavailable');
    console.error(e.detail.error.message);
  }

  // TODO(dhruvsr): allow less priority alerts to override high priority alerts
  // In some use cases we may want generic alerts to show along/over errors
  _canOverride(incoming = ErrorType.GENERIC, existing = ErrorType.GENERIC) {
    return ErrorTypePriority[incoming] >= ErrorTypePriority[existing];
  }

  _showAlert(
    text: string,
    actionText?: string,
    actionCallback?: () => void,
    dismissOnNavigation?: boolean,
    type?: ErrorType
  ) {
    if (this._alertElement) {
      // check priority before hiding
      if (!this._canOverride(type, this._alertElement.type)) return;
      this._hideAlert();
    }

    this._clearHideAlertHandle();
    if (dismissOnNavigation) {
      // Persist alert until navigation.
      this.listen(document, 'location-change', '_hideAlert');
    } else {
      this._hideAlertHandle = this.async(
        this._hideAlert,
        HIDE_ALERT_TIMEOUT_MS
      );
    }
    const el = this._createToastAlert();
    el.show(text, actionText, actionCallback);
    this._alertElement = el;
    this.fire('iron-announce', {text}, {bubbles: true});
    this.reporting.reportInteraction('show-alert', {text});
  }

  _hideAlert() {
    if (!this._alertElement) {
      return;
    }

    this._alertElement.hide();
    this._alertElement = null;

    // Remove listener for page navigation, if it exists.
    this.unlisten(document, 'location-change', '_hideAlert');
  }

  _clearHideAlertHandle() {
    if (this._hideAlertHandle !== null) {
      this.cancelAsync(this._hideAlertHandle);
      this._hideAlertHandle = null;
    }
  }

  _showAuthErrorAlert(errorText: string, actionText?: string) {
    // hide any existing alert like `reload`
    // as auth error should have the highest priority
    if (this._alertElement) {
      this._alertElement.hide();
    }

    this._alertElement = this._createToastAlert();
    this._alertElement.type = ErrorType.AUTH;
    this._alertElement.show(errorText, actionText, () =>
      this._createLoginPopup()
    );
    this.fire('iron-announce', {text: errorText}, {bubbles: true});
    this._refreshingCredentials = true;
    this._requestCheckLoggedIn();
    if (!document.hidden) {
      this._handleVisibilityChange();
    }
  }

  _createToastAlert() {
    const el = document.createElement('gr-alert');
    el.toast = true;
    return el;
  }

  _handleVisibilityChange() {
    // Ignore when the page is transitioning to hidden (or hidden is
    // undefined).
    if (document.hidden !== false) {
      return;
    }

    // If not currently refreshing credentials and the credentials are old,
    // request them to confirm their validity or (display an auth toast if it
    // fails).
    const timeSinceLastCheck = Date.now() - this._lastCredentialCheck;
    if (
      !this._refreshingCredentials &&
      this.knownAccountId !== undefined &&
      timeSinceLastCheck > STALE_CREDENTIAL_THRESHOLD_MS
    ) {
      this._lastCredentialCheck = Date.now();

      // check auth status in case:
      // - user signed out
      // - user switched account
      this._checkSignedIn();
    }
  }

  _requestCheckLoggedIn() {
    this.debounce(
      'checkLoggedIn',
      this._checkSignedIn,
      CHECK_SIGN_IN_INTERVAL_MS
    );
  }

  _checkSignedIn() {
    this._lastCredentialCheck = Date.now();

    // force to refetch account info
    this.$.restAPI.invalidateAccountsCache();
    this._authService.clearCache();

    this.$.restAPI.getLoggedIn().then(isLoggedIn => {
      // do nothing if its refreshing
      if (!this._refreshingCredentials) return;

      if (!isLoggedIn) {
        // check later
        // 1. guest mode
        // 2. or signed out
        // in case #2, auth-error is taken care of separately
        this._requestCheckLoggedIn();
      } else {
        // check account
        this.$.restAPI.getAccount().then(account => {
          if (this._refreshingCredentials) {
            // If the credentials were refreshed but the account is different
            // then reload the page completely.
            if (account?._account_id !== this.knownAccountId) {
              this._reloadPage();
              return;
            }

            this._handleCredentialRefreshed();
          }
        });
      }
    });
  }

  _reloadPage() {
    window.location.reload();
  }

  _createLoginPopup() {
    const left = window.screenLeft + (window.outerWidth - SIGN_IN_WIDTH_PX) / 2;
    const top = window.screenTop + (window.outerHeight - SIGN_IN_HEIGHT_PX) / 2;
    const options = [
      `width=${SIGN_IN_WIDTH_PX}`,
      `height=${SIGN_IN_HEIGHT_PX}`,
      `left=${left}`,
      `top=${top}`,
    ];
    window.open(
      getBaseUrl() + '/login/%3FcloseAfterLogin',
      '_blank',
      options.join(',')
    );
    this.listen(window, 'focus', '_handleWindowFocus');
  }

  _handleCredentialRefreshed() {
    this.unlisten(window, 'focus', '_handleWindowFocus');
    this._refreshingCredentials = false;
    this._hideAlert();
    this._showAlert('Credentials refreshed.');
    this.$.noInteractionOverlay.close();

    // Clear the cache for auth
    this._authService.clearCache();
  }

  _handleWindowFocus() {
    this.flushDebouncer('checkLoggedIn');
  }

  _handleShowErrorDialog(e: CustomEvent) {
    this._showErrorDialog(e.detail.message);
  }

  _handleDismissErrorDialog() {
    this.$.errorOverlay.close();
  }

  _showErrorDialog(message: string, options?: {showSignInButton?: boolean}) {
    this.reporting.reportErrorDialog(message);
    this.$.errorDialog.text = message;
    this.$.errorDialog.showSignInButton =
      !!options && !!options.showSignInButton;
    this.$.errorOverlay.open();
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-error-manager': GrErrorManager;
  }
}
