import { __decorate, __metadata } from "tslib";
import { Injector } from '@angular/core';
import { HttpClient, HttpEventType, HttpRequest } from '@angular/common/http';
import { DynamicOutput, PureRelationsComponent } from '@anglr/dynamic/relations';
import { RelationsEditorMetadata } from '@anglr/dynamic/relations-editor';
import { LOGGER, ProgressIndicatorService } from '@anglr/common';
import { handleHeaderParam, handlePathParam, handleQueryObjectParam, handleQueryParam, mergeQueryObjectParamsWithHttpParams, QueryStringSerializer } from '@anglr/rest';
import { isBlank, isEmptyObject } from '@jscrpt/common';
import { catchError } from 'rxjs/operators';
import { EMPTY } from 'rxjs';
import { RestRelationsMetadataLoader } from './rest.metadata';
//TODO: add required to rest param
/**
 * Rest relations component
 */
let RestRelations = class RestRelations {
    //######################### public properties - implementation of RelationsComponent #########################
    /**
     * @inheritdoc
     */
    get relationsOptions() {
        return this.ɵRelationsOptions;
    }
    set relationsOptions(value) {
        this.ɵRelationsOptions = value;
        this.initialize();
    }
    //######################### constructor #########################
    constructor(injector) {
        /**
         * Indication whether there is null or undefined required param
         */
        this.emptyParam = [];
        this.http = injector.get(HttpClient);
        this.logger = injector.get(LOGGER);
        this.queryStringSerializer = injector.get(QueryStringSerializer);
        this.progressIndicator = injector.get(ProgressIndicatorService);
    }
    //######################### public methods - implementation of RelationsComponent #########################
    /**
     * @inheritdoc
     */
    ngOnChanges(_changes) {
        this.makeRequest();
    }
    /**
     * @inheritdoc
     */
    invalidateVisuals() {
    }
    //######################### protected methods #########################
    /**
     * Initialize rest relations
     */
    initialize() {
        var _a;
        if (this.relationsOptions) {
            if (this.relationsOptions.params && Array.isArray(this.relationsOptions.params)) {
                for (const index in this.relationsOptions.params) {
                    const param = this.relationsOptions.params[index];
                    this.emptyParam.push(true);
                    if (param.configurable && param.name) {
                        Object.defineProperty(this, param.name, {
                            configurable: true,
                            enumerable: true,
                            set: value => {
                                param.value = value;
                                this.emptyParam[index] = isBlank(value);
                            },
                            get: () => param.value
                        });
                    }
                }
            }
        }
        if ((_a = this.relationsOptions) === null || _a === void 0 ? void 0 : _a.runImmediately) {
            this.makeRequest();
        }
    }
    /**
     * Make http request
     */
    makeRequest() {
        //on empty param
        if (this.emptyParam.find(itm => itm)) {
            return;
        }
        if (this.runningRequestSubscription) {
            this.runningRequestSubscription.unsubscribe();
            this.progressIndicator.hideProgress();
        }
        if (!this.relationsOptions ||
            !this.relationsOptions.method ||
            !this.relationsOptions.url) {
            this.logger.warn('RestRelations: missing options for craeting http request {{@data}}', { data: this.relationsOptions });
            return;
        }
        let body = null;
        let url = this.relationsOptions.url;
        const params = {};
        const headers = {};
        const queryStrings = [];
        if (this.relationsOptions.params && Array.isArray(this.relationsOptions.params)) {
            for (const param of this.relationsOptions.params) {
                if (!param.name) {
                    continue;
                }
                const data = {
                    index: 0,
                    key: param.name,
                    value: param.value,
                    transformFn: null
                };
                switch (param.type) {
                    case 'PATH':
                        {
                            url = handlePathParam(data, url);
                            break;
                        }
                    case 'BODY':
                        {
                            body = param.value;
                            break;
                        }
                    case 'QUERY':
                        {
                            handleQueryParam(data, params);
                            break;
                        }
                    case 'QUERY OBJECT':
                        {
                            handleQueryObjectParam(data, queryStrings, this.queryStringSerializer);
                            break;
                        }
                    case 'HEADER':
                        {
                            handleHeaderParam(data, headers);
                            break;
                        }
                    default:
                        {
                            break;
                        }
                }
            }
        }
        let request = new HttpRequest(this.relationsOptions.method, url, body, {
            reportProgress: false,
            responseType: 'json',
        });
        // query params
        if (!isEmptyObject(params)) {
            request = request.clone({
                setParams: params
            });
        }
        // header params
        if (!isEmptyObject(headers)) {
            request = request.clone({
                setHeaders: headers
            });
        }
        // query object params
        if (queryStrings.length) {
            const requestParams = mergeQueryObjectParamsWithHttpParams(queryStrings, request.params);
            request = request.clone({
                params: requestParams
            });
        }
        this.runningRequestSubscription = this.http.request(request)
            .pipe(catchError(error => {
            //TODO: proper handling
            this.success = null;
            this.error = error;
            return EMPTY;
        }))
            .subscribe(result => {
            if (result.type == HttpEventType.Response) {
                if (result.status >= 200 && result.status <= 300) {
                    this.success = result.body;
                    this.error = null;
                    return;
                }
            }
        });
    }
};
__decorate([
    DynamicOutput(),
    __metadata("design:type", Object)
], RestRelations.prototype, "success", void 0);
__decorate([
    DynamicOutput(),
    __metadata("design:type", Object)
], RestRelations.prototype, "error", void 0);
RestRelations = __decorate([
    PureRelationsComponent(),
    RelationsEditorMetadata(RestRelationsMetadataLoader),
    __metadata("design:paramtypes", [Injector])
], RestRelations);
export { RestRelations };
//# sourceMappingURL=rest.relations.js.map