import { __assign, __decorate, __awaiter, __generator, __param } from 'tslib';
import { BehaviorSubject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { Injectable, Optional, SkipSelf, NgModule } from '@angular/core';
import { HttpClient, HttpClientModule } from '@angular/common/http';

var ApiConfig = /** @class */ (function () {
    function ApiConfig() {
    }
    return ApiConfig;
}());

var DataSourceRequest = /** @class */ (function () {
    function DataSourceRequest() {
        // Data.
        this._request$ = new BehaviorSubject(null);
        this._loading$ = new BehaviorSubject(true);
    }
    Object.defineProperty(DataSourceRequest.prototype, "loading", {
        get: function () {
            return this._loading$.asObservable();
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(DataSourceRequest.prototype, "when", {
        get: function () {
            return this._request$.pipe(filter(function (data) { return !!data; }));
        },
        enumerable: true,
        configurable: true
    });
    DataSourceRequest.prototype.startLoading = function () {
        this._loading$.next(true);
    };
    DataSourceRequest.prototype.stopLoading = function () {
        this._loading$.next(false);
    };
    DataSourceRequest.prototype.update = function (params) {
        if (params === void 0) { params = {}; }
        var currentValue = this._request$.getValue();
        // Set the page number to 1 if the query or page size was changed.
        if (currentValue && params && (currentValue.query !== params.query || currentValue.pageSize !== params.pageSize)) {
            params.pageNumber = 1;
        }
        this._request$.next(__assign(__assign({}, currentValue), params));
    };
    return DataSourceRequest;
}());
var ApiDataSource = /** @class */ (function () {
    function ApiDataSource() {
    }
    return ApiDataSource;
}());

var ApiMapper = /** @class */ (function () {
    function ApiMapper() {
    }
    ApiMapper.prototype.toPageResponse = function (data) {
        return {
            pageSize: data['page_size'],
            pageNumber: data['page_number'],
            totalPages: data['total_pages'],
            totalEntries: data['total_entries'],
            data: data['data']
        };
    };
    ApiMapper.prototype.toPageRequest = function (data) {
        var params = {};
        params['page'] = "" + (data.pageNumber || 1);
        params['page_size'] = "" + (data.pageSize || 25);
        var sort = (data.sort || [])
            .map(function (_a) {
            var name = _a.name;
            return name;
        })
            .filter(function (name) { return !!name; })
            .join(',');
        var sortDirection = (data.sort || [])
            .map(function (_a) {
            var direction = _a.direction;
            return direction;
        })
            .filter(function (direction) { return !!direction; })
            .join(',');
        if (sort.length > 0 && sortDirection.length > 0) {
            params['sort'] = sort;
            params['sort_direction'] = sortDirection;
        }
        if (data.query && data.query.length > 0 && data.queryFields && data.queryFields.length > 0) {
            params['query'] = data.query;
            params['query_fields'] = data.queryFields.join(',');
        }
        return params;
    };
    ApiMapper = __decorate([
        Injectable()
    ], ApiMapper);
    return ApiMapper;
}());

var Api = /** @class */ (function () {
    function Api(_http, _mapper, _config) {
        this._http = _http;
        this._mapper = _mapper;
        this._config = _config;
        // Validate the config exists.
        if (!this._config) {
            throw new Error('API configuration was not received properly.');
        }
        // Cache the base url.
        this._baseUrl = this._config.baseUrl;
    }
    Api.prototype.page = function (endpoint, params, options) {
        var _this = this;
        if (params === void 0) { params = {}; }
        // Compose the params and headers.
        var pageParams = this._mapper.toPageRequest(params);
        var extraParams = (options && options.params) || {};
        var extraHeaders = (options && options.headers) || {};
        // Return an observable so it can be a stream.
        return this.get(endpoint, {
            headers: extraHeaders,
            params: __assign(__assign({}, pageParams), extraParams)
        }).pipe(map(function (response) { return _this._mapper.toPageResponse(response); }));
    };
    Api.prototype.get = function (endpoint, options) {
        // Add the base url to the endpoint.
        var url = this.toAbsoluteUrl(endpoint);
        // Return an observable so it can be a stream.
        return this._http.get(url, options);
    };
    Api.prototype.post = function (endpoint, body) {
        return __awaiter(this, void 0, void 0, function () {
            var url;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        url = this.toAbsoluteUrl(endpoint);
                        return [4 /*yield*/, this._http.post(url, body).toPromise()];
                    case 1: 
                    // Execute the post call as a promise.
                    return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    Api.prototype.put = function (endpoint, body) {
        return __awaiter(this, void 0, void 0, function () {
            var url;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        url = this.toAbsoluteUrl(endpoint);
                        return [4 /*yield*/, this._http.put(url, body).toPromise()];
                    case 1: 
                    // Execute the put call as a promise.
                    return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    Api.prototype.patch = function (endpoint, body) {
        return __awaiter(this, void 0, void 0, function () {
            var url;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        url = this.toAbsoluteUrl(endpoint);
                        return [4 /*yield*/, this._http.patch(url, body).toPromise()];
                    case 1: 
                    // Execute the patch call as a promise.
                    return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    Api.prototype.delete = function (endpoint) {
        return __awaiter(this, void 0, void 0, function () {
            var url;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        url = this.toAbsoluteUrl(endpoint);
                        return [4 /*yield*/, this._http.delete(url).toPromise()];
                    case 1: 
                    // Execute the delete call as a promise.
                    return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    Api.prototype.toAbsoluteUrl = function (endpoint) {
        return "" + this._baseUrl + endpoint;
    };
    Api.ctorParameters = function () { return [
        { type: HttpClient },
        { type: ApiMapper },
        { type: ApiConfig, decorators: [{ type: Optional }] }
    ]; };
    Api = __decorate([
        Injectable(),
        __param(2, Optional())
    ], Api);
    return Api;
}());

var ApiError = /** @class */ (function () {
    function ApiError(_status, _error) {
        this._status = _status;
        this._error = _error;
    }
    Object.defineProperty(ApiError.prototype, "status", {
        get: function () {
            return this._status;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(ApiError.prototype, "error", {
        get: function () {
            return this._error;
        },
        enumerable: true,
        configurable: true
    });
    ApiError.prototype.get = function (token, delimiter) {
        if (delimiter === void 0) { delimiter = '.'; }
        var tokens = (token || '').split(delimiter);
        var result = tokens.reduce(function (previous, token) {
            if (previous && previous[token]) {
                return previous[token];
            }
            return null;
        }, this._error || {});
        return result;
    };
    ApiError.prototype.has = function (token, delimiter) {
        if (delimiter === void 0) { delimiter = '.'; }
        return !!this.get(token, delimiter);
    };
    ApiError.prototype.includes = function (token, value) {
        var array = this.get(token);
        return (array || []).includes(value);
    };
    return ApiError;
}());

var ApiModule = /** @class */ (function () {
    function ApiModule(_parent) {
        if (_parent) {
            throw new Error('ApiModule is already loaded; Import it in the AppModule only.');
        }
    }
    ApiModule_1 = ApiModule;
    ApiModule.forRoot = function (config) {
        return {
            ngModule: ApiModule_1,
            providers: [
                { provide: ApiConfig, useValue: config },
                Api
            ]
        };
    };
    var ApiModule_1;
    ApiModule.ctorParameters = function () { return [
        { type: ApiModule, decorators: [{ type: Optional }, { type: SkipSelf }] }
    ]; };
    ApiModule = ApiModule_1 = __decorate([
        NgModule({
            imports: [
                HttpClientModule
            ],
            providers: [
                { provide: ApiMapper, useClass: ApiMapper }
            ]
        }),
        __param(0, Optional()), __param(0, SkipSelf())
    ], ApiModule);
    return ApiModule;
}());

/**
 * Generated bundle index. Do not edit.
 */

export { Api, ApiConfig, ApiDataSource, ApiError, ApiMapper, ApiModule, DataSourceRequest };
//# sourceMappingURL=bravobit-bb-foundation-api.js.map
