/**
 * @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.js';
import '../../shared/gr-alert/gr-alert.js';
import '../../shared/gr-overlay/gr-overlay.js';
import '../../shared/gr-rest-api-interface/gr-rest-api-interface.js';
import '../../shared/gr-js-api-interface/gr-js-api-interface.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-error-manager_html.js';
import {BaseUrlBehavior} from '../../../behaviors/base-url-behavior/base-url-behavior.js';
import {authService} from '../../shared/gr-rest-api-interface/gr-auth.js';
import {appContext} from '../../../services/app-context.js';

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';

/**
 * @extends PolymerElement
 */
class GrErrorManager extends mixinBehaviors( [
  BaseUrlBehavior,
], GestureEventListeners(
    LegacyElementMixin(
        PolymerElement))) {
  static get template() { return htmlTemplate; }

  static get is() { return 'gr-error-manager'; }

  static get properties() {
    return {
    /**
     * The ID of the account that was logged in when the app was launched. If
     * not set, then there was no account at launch.
     */
      knownAccountId: Number,

      /** @type {?Object} */
      _alertElement: Object,
      /** @type {?number} */
      _hideAlertHandle: Number,
      _refreshingCredentials: {
        type: Boolean,
        value: false,
      },

      /**
       * The time (in milliseconds) since the most recent credential check.
       */
      _lastCredentialCheck: {
        type: Number,
        value() { return Date.now(); },
      },

      loginUrl: {
        type: String,
        value: '/login',
      },
    };
  }

  constructor() {
    super();

    /** @type {!Auth} */
    this._authService = authService;

    /** @type {?Function} */
    this._authErrorHandlerDeregistrationHook;

    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, 'show-alert', '_handleShowAlert');
    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);
          });
  }

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

    this._authErrorHandlerDeregistrationHook();
  }

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

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

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

  _handleServerError(e) {
    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.log(`server error: ${errorText}`);
    });
  }

  _showNotFoundMessageWithTip({status, statusText, errorText, url, trace}) {
    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}) {
    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) {
    this._showAlert(e.detail.message, e.detail.action, e.detail.callback,
        e.detail.dismissOnNavigation);
  }

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

  /**
   * @param {string} text
   * @param {?string=} opt_actionText
   * @param {?Function=} opt_actionCallback
   * @param {?boolean=} opt_dismissOnNavigation
   */
  _showAlert(text, opt_actionText, opt_actionCallback,
      opt_dismissOnNavigation) {
    if (this._alertElement) {
      // do not override auth alerts
      if (this._alertElement.type === 'AUTH') return;
      this._hideAlert();
    }

    this._clearHideAlertHandle();
    if (opt_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, opt_actionText, opt_actionCallback);
    this._alertElement = el;
  }

  _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, actionText) {
    // 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 = 'AUTH';
    this._alertElement.show(errorText, actionText,
        this._createLoginPopup.bind(this));

    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(this.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) {
    this._showErrorDialog(e.detail.message);
  }

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

  _showErrorDialog(message, opt_options) {
    this.reporting.reportErrorDialog(message);
    this.$.errorDialog.text = message;
    this.$.errorDialog.showSignInButton =
        opt_options && opt_options.showSignInButton;
    this.$.errorOverlay.open();
  }
}

customElements.define(GrErrorManager.is, GrErrorManager);
