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

/**
 * @fileoverview added by tsickle
 * Generated from: lib/interfaces/config.interface.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class ApiConfig {
}
if (false) {
    /** @type {?} */
    ApiConfig.prototype.baseUrl;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/interfaces/mapper.interface.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function ApiMapperProtocol() { }
if (false) {
    /**
     * @template T
     * @param {?} data
     * @return {?}
     */
    ApiMapperProtocol.prototype.toPageResponse = function (data) { };
    /**
     * @param {?} data
     * @return {?}
     */
    ApiMapperProtocol.prototype.toPageRequest = function (data) { };
}
/**
 * @record
 */
function ApiParams() { }

/**
 * @fileoverview added by tsickle
 * Generated from: lib/interfaces/pages.interface.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 * @template T
 */
function ApiPageResponse() { }
if (false) {
    /** @type {?} */
    ApiPageResponse.prototype.totalPages;
    /** @type {?} */
    ApiPageResponse.prototype.totalEntries;
    /** @type {?} */
    ApiPageResponse.prototype.pageSize;
    /** @type {?} */
    ApiPageResponse.prototype.pageNumber;
    /** @type {?} */
    ApiPageResponse.prototype.data;
}
/**
 * @record
 */
function ApiPageRequest() { }
if (false) {
    /** @type {?} */
    ApiPageRequest.prototype.pageNumber;
    /** @type {?} */
    ApiPageRequest.prototype.pageSize;
    /** @type {?} */
    ApiPageRequest.prototype.query;
    /** @type {?} */
    ApiPageRequest.prototype.queryFields;
    /** @type {?} */
    ApiPageRequest.prototype.sort;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/interfaces/datasource.interface.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class DataSourceRequest {
    constructor() {
        // Data.
        this._request$ = new BehaviorSubject(null);
        this._loading$ = new BehaviorSubject(true);
    }
    /**
     * @return {?}
     */
    get loading() {
        return this._loading$.asObservable();
    }
    /**
     * @return {?}
     */
    get when() {
        return this._request$.pipe(filter((/**
         * @param {?} data
         * @return {?}
         */
        data => !!data)));
    }
    /**
     * @return {?}
     */
    startLoading() {
        this._loading$.next(true);
    }
    /**
     * @return {?}
     */
    stopLoading() {
        this._loading$.next(false);
    }
    /**
     * @param {?=} params
     * @return {?}
     */
    update(params = {}) {
        /** @type {?} */
        const 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(Object.assign({}, currentValue, params));
    }
}
if (false) {
    /**
     * @type {?}
     * @private
     */
    DataSourceRequest.prototype._request$;
    /**
     * @type {?}
     * @private
     */
    DataSourceRequest.prototype._loading$;
}
/**
 * @abstract
 * @template T
 */
class ApiDataSource {
}
if (false) {
    /**
     * @abstract
     * @param {?} request
     * @return {?}
     */
    ApiDataSource.prototype.handle = function (request) { };
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/api.mapper.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class ApiMapper {
    /**
     * @template T
     * @param {?} data
     * @return {?}
     */
    toPageResponse(data) {
        return {
            pageSize: (/** @type {?} */ (data['page_size'])),
            pageNumber: (/** @type {?} */ (data['page_number'])),
            totalPages: (/** @type {?} */ (data['total_pages'])),
            totalEntries: (/** @type {?} */ (data['total_entries'])),
            data: (/** @type {?} */ (data['data']))
        };
    }
    /**
     * @param {?} data
     * @return {?}
     */
    toPageRequest(data) {
        /** @type {?} */
        const params = {};
        params['page'] = `${data.pageNumber || 1}`;
        params['page_size'] = `${data.pageSize || 25}`;
        /** @type {?} */
        const sort = (data.sort || [])
            .map((/**
         * @param {?} __0
         * @return {?}
         */
        ({ name }) => name))
            .filter((/**
         * @param {?} name
         * @return {?}
         */
        name => !!name))
            .join(',');
        /** @type {?} */
        const sortDirection = (data.sort || [])
            .map((/**
         * @param {?} __0
         * @return {?}
         */
        ({ direction }) => direction))
            .filter((/**
         * @param {?} direction
         * @return {?}
         */
        direction => !!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;
    }
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/api.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class Api {
    /**
     * @param {?} _http
     * @param {?} _mapper
     * @param {?} _config
     */
    constructor(_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;
    }
    /**
     * @template T
     * @param {?} endpoint
     * @param {?=} params
     * @param {?=} options
     * @return {?}
     */
    page(endpoint, params = {}, options) {
        // Compose the params and headers.
        /** @type {?} */
        const pageParams = this._mapper.toPageRequest(params);
        /** @type {?} */
        const extraParams = (options && options.params) || {};
        /** @type {?} */
        const extraHeaders = (options && options.headers) || {};
        // Return an observable so it can be a stream.
        return this.get(endpoint, {
            headers: extraHeaders,
            params: Object.assign({}, pageParams, extraParams)
        }).pipe(map((/**
         * @param {?} response
         * @return {?}
         */
        response => this._mapper.toPageResponse(response))));
    }
    /**
     * @template T
     * @param {?} endpoint
     * @param {?=} options
     * @return {?}
     */
    get(endpoint, options) {
        // Add the base url to the endpoint.
        /** @type {?} */
        const url = this.toAbsoluteUrl(endpoint);
        // Return an observable so it can be a stream.
        return this._http.get(url, options);
    }
    /**
     * @template T
     * @param {?} endpoint
     * @param {?=} body
     * @return {?}
     */
    post(endpoint, body) {
        return __awaiter(this, void 0, void 0, function* () {
            // Add the base url to the endpoint.
            /** @type {?} */
            const url = this.toAbsoluteUrl(endpoint);
            // Execute the post call as a promise.
            return yield this._http.post(url, body).toPromise();
        });
    }
    /**
     * @template T
     * @param {?} endpoint
     * @param {?} body
     * @return {?}
     */
    put(endpoint, body) {
        return __awaiter(this, void 0, void 0, function* () {
            // Add the base url to the endpoint.
            /** @type {?} */
            const url = this.toAbsoluteUrl(endpoint);
            // Execute the put call as a promise.
            return yield this._http.put(url, body).toPromise();
        });
    }
    /**
     * @template T
     * @param {?} endpoint
     * @return {?}
     */
    delete(endpoint) {
        return __awaiter(this, void 0, void 0, function* () {
            // Add the base url to the endpoint.
            /** @type {?} */
            const url = this.toAbsoluteUrl(endpoint);
            // Execute the delete call as a promise.
            return yield this._http.delete(url).toPromise();
        });
    }
    /**
     * @private
     * @param {?} endpoint
     * @return {?}
     */
    toAbsoluteUrl(endpoint) {
        return `${this._baseUrl}${endpoint}`;
    }
}
Api.decorators = [
    { type: Injectable }
];
/** @nocollapse */
Api.ctorParameters = () => [
    { type: HttpClient },
    { type: ApiMapper },
    { type: ApiConfig, decorators: [{ type: Optional }] }
];
if (false) {
    /**
     * @type {?}
     * @private
     */
    Api.prototype._baseUrl;
    /**
     * @type {?}
     * @private
     */
    Api.prototype._http;
    /**
     * @type {?}
     * @private
     */
    Api.prototype._mapper;
    /**
     * @type {?}
     * @private
     */
    Api.prototype._config;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/api.error.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class ApiError {
    /**
     * @param {?} _status
     * @param {?} _error
     */
    constructor(_status, _error) {
        this._status = _status;
        this._error = _error;
    }
    /**
     * @return {?}
     */
    get status() {
        return this._status;
    }
    /**
     * @return {?}
     */
    get error() {
        return this._error;
    }
    /**
     * @template T
     * @param {?} token
     * @param {?=} delimiter
     * @return {?}
     */
    get(token, delimiter = '.') {
        /** @type {?} */
        const tokens = (token || '').split(delimiter);
        /** @type {?} */
        const result = tokens.reduce((/**
         * @param {?} previous
         * @param {?} token
         * @return {?}
         */
        (previous, token) => {
            if (previous && previous[token]) {
                return previous[token];
            }
            return null;
        }), this._error || {});
        return (/** @type {?} */ (result));
    }
    /**
     * @param {?} token
     * @param {?=} delimiter
     * @return {?}
     */
    has(token, delimiter = '.') {
        return !!this.get(token, delimiter);
    }
    /**
     * @param {?} token
     * @param {?} value
     * @return {?}
     */
    includes(token, value) {
        /** @type {?} */
        const array = this.get(token);
        return (array || []).includes(value);
    }
}
if (false) {
    /**
     * @type {?}
     * @private
     */
    ApiError.prototype._status;
    /**
     * @type {?}
     * @private
     */
    ApiError.prototype._error;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/api.module.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class ApiModule {
    /**
     * @param {?} _parent
     */
    constructor(_parent) {
        if (_parent) {
            throw new Error('ApiModule is already loaded; Import it in the AppModule only.');
        }
    }
    /**
     * @param {?} config
     * @return {?}
     */
    static forRoot(config) {
        return {
            ngModule: ApiModule,
            providers: [
                { provide: ApiConfig, useValue: config },
                Api
            ]
        };
    }
}
ApiModule.decorators = [
    { type: NgModule, args: [{
                imports: [
                    HttpClientModule
                ],
                providers: [
                    { provide: ApiMapper, useClass: ApiMapper }
                ]
            },] }
];
/** @nocollapse */
ApiModule.ctorParameters = () => [
    { type: ApiModule, decorators: [{ type: Optional }, { type: SkipSelf }] }
];

/**
 * @fileoverview added by tsickle
 * Generated from: public_api.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * Generated from: bravobit-bb-foundation-api.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

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