// 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.
(function(window) {
  'use strict';

  // Prevent redefinition.
  if (window.GrGapiAuth) { return; }

  const EMAIL_SCOPE = 'email';

  function GrGapiAuth() {}

  GrGapiAuth._loadGapiPromise = null;
  GrGapiAuth._setupPromise = null;
  GrGapiAuth._refreshTokenPromise = null;
  GrGapiAuth._sharedAuthToken = null;
  GrGapiAuth._oauthClientId = null;
  GrGapiAuth._oauthEmail = null;

  GrGapiAuth.prototype.fetch = function(url, options) {
    options = Object.assign({}, options);
    return this._getAccessToken().then(
        token => window.FASTER_GERRIT_CORS ?
            this._fasterGerritCors(url, options, token) :
            this._defaultFetch(url, options, token)
    );
  };

  GrGapiAuth.prototype._defaultFetch = function(url, options, token) {
    if (token) {
      options.headers = options.headers || new Headers();
      options.headers.append('Authorization', `Bearer ${token}`);
      if (!url.startsWith('/a/')) {
        url = '/a' + url;
      }
    }
    return fetch(url, options);
  };

  GrGapiAuth.prototype._fasterGerritCors = function(url, options, token) {
    const method = options.method || 'GET';
    if (method === 'GET') {
      return fetch(url, options);
    }
    const params = [];
    if (token) {
      params.push(`access_token=${token}`);
    }
    const contentType = options.headers && options.headers.get('Content-Type');
    if (contentType) {
      options.headers.set('Content-Type', 'text/plain');
      params.push(`$ct=${encodeURIComponent(contentType)}`);
    }
    params.push(`$m=${method}`);
    url = url + (url.indexOf('?') === -1 ? '?' : '') + params.join('&');
    options.method = 'POST';
    return fetch(url, options);
  };

  GrGapiAuth.prototype._getAccessToken = function() {
    if (this._isTokenValid(GrGapiAuth._sharedAuthToken)) {
      return Promise.resolve(GrGapiAuth._sharedAuthToken.access_token);
    }
    if (!GrGapiAuth._refreshTokenPromise) {
      GrGapiAuth._refreshTokenPromise = this._loadGapi()
        .then(() => this._configureOAuthLibrary())
        .then(() => this._refreshToken())
        .then(token => {
          GrGapiAuth._sharedAuthToken = token;
          GrGapiAuth._refreshTokenPromise = null;
          return this._getAccessToken();
        }).catch(err => {
          console.error(err);
        });
    }
    return GrGapiAuth._refreshTokenPromise;
  };

  GrGapiAuth.prototype._isTokenValid = function(token) {
    if (!token) { return false; }
    if (!token.access_token || !token.expires_at) { return false; }

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

    return true;
  };

  GrGapiAuth.prototype._loadGapi = function() {
    if (!GrGapiAuth._loadGapiPromise) {
      GrGapiAuth._loadGapiPromise = new Promise((resolve, reject) => {
        const scriptEl = document.createElement('script');
        scriptEl.defer = true;
        scriptEl.async = true;
        scriptEl.src = 'https://apis.google.com/js/platform.js';
        scriptEl.onerror = reject;
        scriptEl.onload = resolve;
        document.body.appendChild(scriptEl);
      });
    }
    return GrGapiAuth._loadGapiPromise;
  };

  GrGapiAuth.prototype._configureOAuthLibrary = function() {
    if (!GrGapiAuth._setupPromise) {
      GrGapiAuth._setupPromise = new Promise(
        resolve => gapi.load('config_min', resolve)
      )
        .then(() => this._getOAuthConfig())
        .then(config => {
          if (config.hasOwnProperty('auth_url') && config.auth_url) {
            gapi.config.update('oauth-flow/authUrl', config.auth_url);
          }
          if (config.hasOwnProperty('proxy_url') && config.proxy_url) {
            gapi.config.update('oauth-flow/proxyUrl', config.proxy_url);
          }
          GrGapiAuth._oauthClientId = config.client_id;
          GrGapiAuth._oauthEmail = config.email;

          // Loading auth has a side-effect. The URLs should be set before
          // loading it.
          return new Promise(
            resolve => gapi.load('auth', () => gapi.auth.init(resolve))
          );
        });
    }
    return GrGapiAuth._setupPromise;
  };

  GrGapiAuth.prototype._refreshToken = function() {
    const opts = {
      client_id: GrGapiAuth._oauthClientId,
      immediate: true,
      scope: EMAIL_SCOPE,
      login_hint: GrGapiAuth._oauthEmail,
    };
    return new Promise((resolve, reject) => {
      gapi.auth.authorize(opts, token => {
        if (!token) {
          reject('No token returned');
        } else if (token.error) {
          reject(token.error);
        } else {
          resolve(token);
        }
      });
    });
  };

  GrGapiAuth.prototype._getOAuthConfig = function() {
    const authConfigURL = '/accounts/self/oauthconfig';
    const opts = {
      headers: new Headers({Accept: 'application/json'}),
      credentials: 'same-origin',
    };
    return fetch(authConfigURL, opts).then(response => {
      if (!response.ok) {
        console.error(response.statusText);
        if (response.body && response.body.then) {
          return response.body.then(text => {
            return Promise.reject(text);
          });
        }
        if (response.statusText) {
          return Promise.reject(response.statusText);
        } else {
          return Promise.reject('_getOAuthConfig' + response.status);
        }
      }
      return this._getResponseObject(response);
    });
  };

  GrGapiAuth.prototype._getResponseObject = function(response) {
    const JSON_PREFIX = ')]}\'';
    return response.text().then(text => {
      return JSON.parse(text.substring(JSON_PREFIX.length));
    });
  },

  window.GrGapiAuth = GrGapiAuth;
})(window);
