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 { ChangeDetectorRef, Component, ElementRef, Input } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { Stratus } from '@stratusjs/runtime/stratus';
import _, { has } from 'lodash';
import { cookie } from '@stratusjs/core/environment';
import { RootComponent } from '../core/root.component';
import { Observable, Subject, timer } from 'rxjs';
import { FormBuilder, FormControl } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { EventManager } from '@stratusjs/core/events/eventManager';
import { catchError, debounce } from 'rxjs/operators';
import { Registry } from '@stratusjs/angularjs/services/registry';
const systemDir = '@stratusjs/angular';
const moduleName = 'json';
const min = !cookie('env') ? '.min' : '';
const localDir = `${Stratus.BaseUrl}${boot.configuration.paths[`${systemDir}/*`].replace(/[^/]*$/, '').replace(/\/dist\/$/, '/src/')}`;
let JsonComponent = class JsonComponent extends RootComponent {
    constructor(sanitizer, ref, elementRef, fb, dialog) {
        super();
        this.sanitizer = sanitizer;
        this.ref = ref;
        this.elementRef = elementRef;
        this.fb = fb;
        this.dialog = dialog;
        this.title = `${moduleName}_component`;
        this.dev = !!cookie('env');
        this.debug = !!cookie(`debug_${moduleName}`);
        this._ = _;
        this.has = has;
        this.log = console.log;
        this.Stratus = Stratus;
        this.registry = new Registry();
        this.onChange = new Subject();
        this.svgIcons = {};
        this.initialized = false;
        this.styled = false;
        this.blurred = false;
        this.focused = false;
        this.form = this.fb.group({
            dataString: new FormControl(),
        });
        this.dataChangeLog = [];
        this.incomingData = '';
        this.outgoingData = '';
        this.debounceSave = true;
        this.debounceTime = 5000;
        this.forceSave = false;
        this.uid = _.uniqueId(`sa_${_.snakeCase(moduleName)}_component_`);
        Stratus.Instances[this.uid] = this;
        Stratus.Internals.LoadCss([
            `${localDir}${moduleName}/${moduleName}.component${min}.css`,
        ]).then(() => {
            this.styled = true;
            this.refresh();
        }).catch((e) => {
            console.error(e);
            console.warn('Issue detected in CSS Loader for Component:', this.uid);
            this.styled = true;
            this.refresh();
        });
        this.hydrate(elementRef, sanitizer, ["title", "uid", "dev", "debug", "target", "targetSuffix", "id", "manifest", "decouple", "direct", "api", "urlRoot", "type", "property", "endpoint", "_", "has", "log", "Stratus", "registry", "fetched", "data", "collection", "model", "dataSub", "onChange", "subscriber", "svgIcons", "initialized", "styled", "blurred", "focused", "codeViewIsOpen", "form", "dataChangeLog", "incomingData", "outgoingData", "debounceSave", "debounceTime", "forceSave", "sanitizer", "ref", "elementRef", "fb", "dialog", "ngOnInit", "handleError", "fetchData", "dataDefer", "dataRef", "onDataChange", "modelSave", "hydrate", "disableRefresh", "stagger", "reloading", "refresh", "ngOnDestroy"]);
        this.fetchData()
            .then(data => {
            if (!data || !(data instanceof EventManager)) {
                console.warn('Unable to bind data from Registry!');
                return;
            }
            const onDataChange = () => {
                if (!data.completed) {
                    return;
                }
                this.dataDefer(this.subscriber);
            };
            data.on('change', onDataChange);
            onDataChange();
        });
        this.dataSub = new Observable(subscriber => {
            if (this.dev) {
                console.warn(`[observable] creating subscriber on ${this.uid}`, subscriber);
            }
            return this.dataDefer(subscriber);
        });
        this.dataSub.pipe(debounce(() => timer(250)), catchError(this.handleError)).subscribe(evt => {
            if (this.focused) {
                if (this.dev) {
                    console.warn(`[subscriber] waiting on updates due to focus on ${this.uid}`);
                }
                return;
            }
            const dataControl = this.form.get('dataString');
            if (dataControl.value === evt) {
                if (this.initialized) {
                    this.refresh();
                }
                return;
            }
            dataControl.patchValue(evt);
            this.refresh();
        });
    }
    ngOnInit() {
        this.initialized = true;
        const dataControl = this.form.get('dataString');
        if (this.debounceSave) {
            dataControl.valueChanges.pipe(debounce(() => timer(this.debounceTime)), catchError(this.handleError)).subscribe((evt) => this.modelSave(evt));
            dataControl.valueChanges.pipe(debounce(() => timer(250)), catchError(this.handleError)).subscribe((evt) => {
                if (this.model.changedExternal) {
                    return;
                }
                this.model.changedExternal = true;
                this.model.trigger('change');
            });
            dataControl.valueChanges.forEach((value) => this.outgoingData = value);
        }
        else {
            dataControl.valueChanges.forEach((value) => this.modelSave(value));
        }
    }
    handleError(err) {
        console.error(err);
        return err;
    }
    fetchData() {
        if (this.fetched) {
            return this.fetched;
        }
        return this.fetched = this.registry.fetch(Stratus.Select(this.elementRef.nativeElement), this);
    }
    dataDefer(subscriber) {
        this.subscriber = this.subscriber || subscriber;
        if (!this.subscriber) {
            if (this.dev) {
                console.warn(`[defer] debouncing due to empty subscriber on ${this.uid}`);
            }
            setTimeout(() => {
                if (this.dev) {
                    console.warn(`[defer] debounced subscriber returned on ${this.uid}`);
                }
                this.dataDefer(subscriber);
            }, 250);
            return;
        }
        const prevString = _.clone(this.incomingData);
        const dataString = this.dataRef();
        if (prevString === dataString) {
            return;
        }
        if (!dataString && (!this.data || !this.data.completed)) {
            if (this.dev) {
                console.warn(`[defer] debouncing subscriber due to unavailable data on ${this.uid}`, this.data);
            }
            setTimeout(() => {
                if (this.dev) {
                    console.warn(`[defer] debounced subscriber returned on ${this.uid}`);
                }
                this.dataDefer(subscriber);
            }, 250);
            return;
        }
        if (prevString === dataString) {
            return;
        }
        if (this.dev) {
            console.warn(`[subscriber] new value submitted on ${this.uid}:`, dataString);
        }
        this.subscriber.next(dataString);
    }
    dataRef() {
        if (!this.model) {
            return '';
        }
        return this.incomingData = this.model.get(this.property);
    }
    onDataChange() {
        this.dataDefer(this.subscriber);
        this.refresh();
    }
    modelSave(value) {
        if (!this.model.completed) {
            return;
        }
        this.model.set(this.property, value);
        if (this.debounceSave) {
            this.model.changedExternal = false;
        }
        if (this.forceSave && !_.isEmpty(this.model.getIdentifier())) {
            this.model.save();
        }
    }
};
__decorate([
    Input(),
    __metadata("design:type", String)
], JsonComponent.prototype, "target", void 0);
__decorate([
    Input(),
    __metadata("design:type", String)
], JsonComponent.prototype, "targetSuffix", void 0);
__decorate([
    Input(),
    __metadata("design:type", Number)
], JsonComponent.prototype, "id", void 0);
__decorate([
    Input(),
    __metadata("design:type", Boolean)
], JsonComponent.prototype, "manifest", void 0);
__decorate([
    Input(),
    __metadata("design:type", Boolean)
], JsonComponent.prototype, "decouple", void 0);
__decorate([
    Input(),
    __metadata("design:type", Boolean)
], JsonComponent.prototype, "direct", void 0);
__decorate([
    Input(),
    __metadata("design:type", Object)
], JsonComponent.prototype, "api", void 0);
__decorate([
    Input(),
    __metadata("design:type", String)
], JsonComponent.prototype, "urlRoot", void 0);
__decorate([
    Input(),
    __metadata("design:type", String)
], JsonComponent.prototype, "type", void 0);
__decorate([
    Input(),
    __metadata("design:type", String)
], JsonComponent.prototype, "property", void 0);
__decorate([
    Input(),
    __metadata("design:type", String)
], JsonComponent.prototype, "endpoint", void 0);
JsonComponent = __decorate([
    Component({
        selector: 'sa-json',
        templateUrl: `${localDir}/${moduleName}/${moduleName}.component${min}.html`,
    }),
    __metadata("design:paramtypes", [DomSanitizer,
        ChangeDetectorRef,
        ElementRef,
        FormBuilder,
        MatDialog])
], JsonComponent);
export { JsonComponent };

//# sourceMappingURL=json.component.js.map
