/**
 * @license
 * Copyright (C) 2017 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 {getBaseUrl} from '../../utils/url-util';
import {EventEmitterService} from '../gr-event-interface/gr-event-interface';
import {
  AuthRequestInit,
  AuthService,
  AuthStatus,
  AuthType,
  DefaultAuthOptions,
  GetTokenCallback,
  Token,
} from './gr-auth';

const MAX_AUTH_CHECK_WAIT_TIME_MS = 1000 * 30; // 30s
const MAX_GET_TOKEN_RETRIES = 2;

interface ValidToken extends Token {
  access_token: string;
  expires_at: string;
}

interface AuthRequestInitWithHeaders extends AuthRequestInit {
  // RequestInit define headers as optional property with a type
  // Headers | string[][] | Record<string, string>
  // In Auth class headers property is always set and has type Headers
  headers: Headers;
}

/**
 * Auth class.
 */
export class Auth implements AuthService {
  // TODO(dmfilippov): Remove Type and Status properties, expose AuthType and
  // AuthStatus to API
  static TYPE = {
    XSRF_TOKEN: AuthType.XSRF_TOKEN,
    ACCESS_TOKEN: AuthType.ACCESS_TOKEN,
  };

  static STATUS = {
    UNDETERMINED: AuthStatus.UNDETERMINED,
    AUTHED: AuthStatus.AUTHED,
    NOT_AUTHED: AuthStatus.NOT_AUTHED,
    ERROR: AuthStatus.ERROR,
  };

  static CREDS_EXPIRED_MSG = 'Credentials expired.';

  private authCheckPromise?: Promise<Response>;

  private _last_auth_check_time: number = Date.now();

  private _status = AuthStatus.UNDETERMINED;

  private retriesLeft = MAX_GET_TOKEN_RETRIES;

  private cachedTokenPromise: Promise<Token | null> | null = null;

  private type?: AuthType;

  private defaultOptions: AuthRequestInit = {};

  private getToken: GetTokenCallback;

  public eventEmitter: EventEmitterService;

  constructor(eventEmitter: EventEmitterService) {
    this.getToken = () => Promise.resolve(this.cachedTokenPromise);
    this.eventEmitter = eventEmitter;
  }

  get baseUrl() {
    return getBaseUrl();
  }

  /**
   * Returns if user is authed or not.
   */
  authCheck(): Promise<boolean> {
    if (
      !this.authCheckPromise ||
      Date.now() - this._last_auth_check_time > MAX_AUTH_CHECK_WAIT_TIME_MS
    ) {
      // Refetch after last check expired
      this.authCheckPromise = fetch(`${this.baseUrl}/auth-check`);
      this._last_auth_check_time = Date.now();
    }

    return this.authCheckPromise
      .then(res => {
        // auth-check will return 204 if authed
        // treat the rest as unauthed
        if (res.status === 204) {
          this._setStatus(Auth.STATUS.AUTHED);
          return true;
        } else {
          this._setStatus(Auth.STATUS.NOT_AUTHED);
          return false;
        }
      })
      .catch(() => {
        this._setStatus(AuthStatus.ERROR);
        // Reset authCheckPromise to avoid caching the failed promise
        this.authCheckPromise = undefined;
        return false;
      });
  }

  clearCache() {
    this.authCheckPromise = undefined;
  }

  private _setStatus(status: AuthStatus) {
    if (this._status === status) return;

    if (this._status === AuthStatus.AUTHED) {
      this.eventEmitter.emit('auth-error', {
        message: Auth.CREDS_EXPIRED_MSG,
        action: 'Refresh credentials',
      });
    }
    this._status = status;
  }

  get status() {
    return this._status;
  }

  get isAuthed() {
    return this._status === Auth.STATUS.AUTHED;
  }

  /**
   * Enable cross-domain authentication using OAuth access token.
   */
  setup(getToken: GetTokenCallback, defaultOptions: DefaultAuthOptions) {
    this.retriesLeft = MAX_GET_TOKEN_RETRIES;
    if (getToken) {
      this.type = AuthType.ACCESS_TOKEN;
      this.cachedTokenPromise = null;
      this.getToken = getToken;
    }
    this.defaultOptions = {};
    if (defaultOptions) {
      this.defaultOptions.credentials = defaultOptions.credentials;
    }
  }

  /**
   * Perform network fetch with authentication.
   */
  fetch(url: string, opt_options?: AuthRequestInit): Promise<Response> {
    const options: AuthRequestInitWithHeaders = {
      headers: new Headers(),
      ...this.defaultOptions,
      ...opt_options,
    };
    if (this.type === AuthType.ACCESS_TOKEN) {
      return this._getAccessToken().then(accessToken =>
        this._fetchWithAccessToken(url, options, accessToken)
      );
    } else {
      return this._fetchWithXsrfToken(url, options);
    }
  }

  private _getCookie(name: string): string {
    const key = name + '=';
    let result = '';
    document.cookie.split(';').some(c => {
      c = c.trim();
      if (c.startsWith(key)) {
        result = c.substring(key.length);
        return true;
      }
      return false;
    });
    return result;
  }

  private _isTokenValid(token: Token | null): token is ValidToken {
    if (!token) {
      return false;
    }
    if (!token.access_token || !token.expires_at) {
      return false;
    }

    const expiration = new Date(Number(token.expires_at) * 1000);
    if (Date.now() >= expiration.getTime()) {
      return false;
    }

    return true;
  }

  private _fetchWithXsrfToken(
    url: string,
    options: AuthRequestInitWithHeaders
  ): Promise<Response> {
    if (options.method && options.method !== 'GET') {
      const token = this._getCookie('XSRF_TOKEN');
      if (token) {
        options.headers.append('X-Gerrit-Auth', token);
      }
    }
    options.credentials = 'same-origin';
    return fetch(url, options);
  }

  private _getAccessToken(): Promise<string | null> {
    if (!this.cachedTokenPromise) {
      this.cachedTokenPromise = this.getToken();
    }
    return this.cachedTokenPromise.then(token => {
      if (this._isTokenValid(token)) {
        this.retriesLeft = MAX_GET_TOKEN_RETRIES;
        return token.access_token;
      }
      if (this.retriesLeft > 0) {
        this.retriesLeft--;
        this.cachedTokenPromise = null;
        return this._getAccessToken();
      }
      // Fall back to anonymous access.
      return null;
    });
  }

  private _fetchWithAccessToken(
    url: string,
    options: AuthRequestInitWithHeaders,
    accessToken: string | null
  ): Promise<Response> {
    const params = [];

    if (accessToken) {
      params.push(`access_token=${accessToken}`);
      const baseUrl = this.baseUrl;
      const pathname = baseUrl
        ? url.substring(url.indexOf(baseUrl) + baseUrl.length)
        : url;
      if (!pathname.startsWith('/a/')) {
        url = url.replace(pathname, '/a' + pathname);
      }
    }

    const method = options.method || 'GET';
    let contentType = options.headers.get('Content-Type');

    // For all requests with body, ensure json content type.
    if (!contentType && options.body) {
      contentType = 'application/json';
    }

    if (method !== 'GET') {
      options.method = 'POST';
      params.push(`$m=${method}`);
      // If a request is not GET, and does not have a body, ensure text/plain
      // content type.
      if (!contentType) {
        contentType = 'text/plain';
      }
    }

    if (contentType) {
      options.headers.set('Content-Type', 'text/plain');
      params.push(`$ct=${encodeURIComponent(contentType)}`);
    }

    if (params.length) {
      url = url + (url.indexOf('?') === -1 ? '?' : '&') + params.join('&');
    }
    return fetch(url, options);
  }
}
