var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import { CookieService } from 'ngx-cookie-service';
import { throwError } from 'rxjs';
import { catchError, flatMap } from 'rxjs/operators';
import { HttpErrorService } from './http-error.service';
var HttpService = /** @class */ (function () {
    function HttpService(http, httpErrorService, cookieService) {
        this.http = http;
        this.httpErrorService = httpErrorService;
        this.cookieService = cookieService;
    }
    HttpService_1 = HttpService;
    /**
     *
     * @param url Url resolved using UrlResolverService
     * @param options
     * @returns {Observable<Response>}
     * @see UrlResolverService
     */
    HttpService.prototype.get = function (url, options, redirectIfNotAuthorised) {
        var _this = this;
        if (redirectIfNotAuthorised === void 0) { redirectIfNotAuthorised = true; }
        var call = function () { return _this.http.get(url, _this.sanitiseOptions(options)); };
        return call().pipe(this.refreshAccessTokenAndRetry(call), this.handleError(redirectIfNotAuthorised));
    };
    /**
     *
     * @param url Url resolved using UrlResolverService
     * @param body
     * @param options
     * @returns {Observable<Response>}
     * @see UrlResolverService
     */
    HttpService.prototype.post = function (url, body, options, redirectIfNotAuthorised) {
        var _this = this;
        if (redirectIfNotAuthorised === void 0) { redirectIfNotAuthorised = true; }
        var call = function () { return _this.http.post(url, body, _this.sanitiseOptions(options)); };
        return call().pipe(this.refreshAccessTokenAndRetry(call), this.handleError(redirectIfNotAuthorised));
    };
    /**
     *
     * @param url Url resolved using UrlResolverService
     * @param body
     * @param options
     * @returns {Observable<Response>}
     * @see UrlResolverService
     */
    HttpService.prototype.put = function (url, body, options) {
        var _this = this;
        var call = function () { return _this.http.put(url, body, _this.sanitiseOptions(options)); };
        return call().pipe(this.refreshAccessTokenAndRetry(call), this.handleError());
    };
    /**
     *
     * @param url Url resolved using UrlResolverService
     * @param options
     * @returns {Observable<Response>}
     * @see UrlResolverService
     */
    HttpService.prototype.delete = function (url, options) {
        var _this = this;
        var call = function () { return _this.http.delete(url, _this.sanitiseOptions(options)); };
        return call().pipe(this.refreshAccessTokenAndRetry(call), this.handleError());
    };
    HttpService.prototype.sanitiseOptions = function (options) {
        options = options || {};
        this.sanitiseHeaders(options);
        return options;
    };
    HttpService.prototype.sanitiseHeaders = function (options) {
        if (!options.headers) {
            options.headers = new Headers();
        }
        var accessToken = this.cookieService.get(HttpService_1.COOKIE_ACCESS_TOKEN);
        options.headers.set(HttpService_1.HEADER_AUTHORIZATION, "Bearer " + accessToken);
        if (!options.headers.has(HttpService_1.HEADER_ACCEPT)) {
            options.headers.set(HttpService_1.HEADER_ACCEPT, 'application/json');
        }
        if (!options.headers.has(HttpService_1.HEADER_CONTENT_TYPE)) {
            options.headers.set(HttpService_1.HEADER_CONTENT_TYPE, 'application/json');
        }
        if (null === options.headers.get(HttpService_1.HEADER_CONTENT_TYPE)) {
            options.headers.delete(HttpService_1.HEADER_CONTENT_TYPE);
        }
    };
    /**
     * Catch HTTP 401 errors and attempt to transparently refresh the access token
     * and retry the API call.
     */
    HttpService.prototype.refreshAccessTokenAndRetry = function (retry) {
        var _this = this;
        return catchError(function (error) {
            if (401 === error.status) {
                console.log('Attempting OAuth2 tokens refresh...');
                return _this.http.get('/oauth2/refresh', {
                    // Include  http-only cookie `refresh_token`
                    withCredentials: true,
                }).pipe(flatMap(function () {
                    console.log('Retrying API call...');
                    return retry();
                }));
            }
            return throwError(error);
        });
    };
    /**
     * Apply uniform error handling process to all API calls.
     */
    HttpService.prototype.handleError = function (redirectIfNotAuthorised) {
        var _this = this;
        if (redirectIfNotAuthorised === void 0) { redirectIfNotAuthorised = true; }
        return catchError(function (res) {
            return _this.httpErrorService.handle(res, redirectIfNotAuthorised);
        });
    };
    var HttpService_1;
    HttpService.COOKIE_ACCESS_TOKEN = 'access_token';
    HttpService.HEADER_AUTHORIZATION = 'Authorization';
    HttpService.HEADER_ACCEPT = 'Accept';
    HttpService.HEADER_CONTENT_TYPE = 'Content-Type';
    HttpService = HttpService_1 = __decorate([
        Injectable(),
        __metadata("design:paramtypes", [Http,
            HttpErrorService,
            CookieService])
    ], HttpService);
    return HttpService;
}());
export { HttpService };
//# sourceMappingURL=http.service.js.map