import { __awaiter, __classPrivateFieldGet } from 'tslib';
import { ɵɵdefineInjectable, ɵɵinject, Injectable, Inject, Optional } from '@angular/core';
import hash from 'object-hash';
import { SdApiService } from '@sd-angular/core/api';
import { FIREBASE_CONFIG } from '@sd-angular/core/common';

var _cache, _getUrl, _getKey;
class SdDbService {
    constructor(apiService, firebaseConfiguration) {
        this.apiService = apiService;
        this.firebaseConfiguration = firebaseConfiguration;
        _cache.set(this, {});
        _getUrl.set(this, (args) => {
            const configuration = Object.assign(Object.assign({}, this.firebaseConfiguration), args);
            const { functionUrl, project, env } = configuration;
            if (!functionUrl || !project || !env) {
                throw new Error('No firebase function configuration');
            }
            return {
                find: `${functionUrl}/db/find/${project}/${env}`,
                get: `${functionUrl}/db/get/${project}/${env}`,
                set: `${functionUrl}/db/set/${project}/${env}`,
                remove: `${functionUrl}/db/remove/${project}/${env}`
            };
        });
        _getKey.set(this, (id, args) => {
            var _a, _b, _c;
            const configuration = {
                functionUrl: ((_a = this.firebaseConfiguration) === null || _a === void 0 ? void 0 : _a.functionUrl) || (args === null || args === void 0 ? void 0 : args.functionUrl),
                project: ((_b = this.firebaseConfiguration) === null || _b === void 0 ? void 0 : _b.project) || (args === null || args === void 0 ? void 0 : args.project),
                env: ((_c = this.firebaseConfiguration) === null || _c === void 0 ? void 0 : _c.env) || (args === null || args === void 0 ? void 0 : args.env)
            };
            return hash(Object.assign({ id }, configuration));
        });
        this.register = (collection, option) => {
            const { cacheable } = option || {};
            return {
                get: (id) => __awaiter(this, void 0, void 0, function* () {
                    const key = __classPrivateFieldGet(this, _getKey).call(this, id, option);
                    if (!cacheable || !__classPrivateFieldGet(this, _cache)[key]) {
                        __classPrivateFieldGet(this, _cache)[key] = yield this.get(collection, id, option);
                    }
                    return JSON.parse(JSON.stringify(__classPrivateFieldGet(this, _cache)[key]));
                }),
                set: (id, data) => {
                    const key = __classPrivateFieldGet(this, _getKey).call(this, id, option);
                    delete __classPrivateFieldGet(this, _cache)[key];
                    return this.set(collection, id, data, option);
                },
                remove: (id) => {
                    const key = __classPrivateFieldGet(this, _getKey).call(this, id, option);
                    delete __classPrivateFieldGet(this, _cache)[key];
                    return this.remove(collection, id, option);
                },
                find: (query) => this.find(collection, query, option),
                copy: (source, toId) => {
                    const key = __classPrivateFieldGet(this, _getKey).call(this, toId, option);
                    delete __classPrivateFieldGet(this, _cache)[key];
                    return this.copy(collection, source, toId, option);
                }
            };
        };
        this.get = (collection, id, option) => __awaiter(this, void 0, void 0, function* () {
            const url = `${__classPrivateFieldGet(this, _getUrl).call(this, option).get}/${collection}/${id}`;
            return yield this.apiService.get(url);
        });
        this.set = (collection, id, data, option) => __awaiter(this, void 0, void 0, function* () {
            const url = `${__classPrivateFieldGet(this, _getUrl).call(this, option).set}/${collection}/${id}`;
            yield this.apiService.post(url, data);
        });
        this.remove = (collection, id, option) => __awaiter(this, void 0, void 0, function* () {
            const url = `${__classPrivateFieldGet(this, _getUrl).call(this, option).remove}/${collection}/${id}`;
            yield this.apiService.delete(url);
        });
        this.find = (collection, query, option) => __awaiter(this, void 0, void 0, function* () {
            const url = `${__classPrivateFieldGet(this, _getUrl).call(this, option).find}/${collection}`;
            return yield this.apiService.post(url, query);
        });
        this.copy = (collection, source, toId, option) => __awaiter(this, void 0, void 0, function* () {
            const res = yield this.get(collection, source.fromId, Object.assign(Object.assign({}, option), source));
            return yield this.set(collection, toId, res.data, option);
        });
        this.clone = (args, from) => __awaiter(this, void 0, void 0, function* () {
            if (!this.hasConfiguration) {
                throw new Error('No firebase function configuration');
            }
            const { functionUrl, project, env } = this.firebaseConfiguration;
            const fromFunctionUrl = (from === null || from === void 0 ? void 0 : from.functionUrl) || functionUrl;
            const fromProject = (from === null || from === void 0 ? void 0 : from.project) || project;
            const fromEnv = from === null || from === void 0 ? void 0 : from.env;
            const fromCollection = from === null || from === void 0 ? void 0 : from.collection;
            const fromDocumentId = from === null || from === void 0 ? void 0 : from.documentId;
            const toCollection = (args === null || args === void 0 ? void 0 : args.collection) || (from === null || from === void 0 ? void 0 : from.collection);
            const toDocumentId = (args === null || args === void 0 ? void 0 : args.documentId) || (from === null || from === void 0 ? void 0 : from.documentId);
            const fromUrl = `${fromFunctionUrl}/db/get/${fromProject}/${fromEnv}/${fromCollection}/${fromDocumentId}`;
            const document = yield this.apiService.get(fromUrl);
            yield this.set(toCollection, toDocumentId, document.data);
        });
    }
    get hasConfiguration() {
        var _a, _b, _c;
        return !!((_a = this.firebaseConfiguration) === null || _a === void 0 ? void 0 : _a.functionUrl) && !!((_b = this.firebaseConfiguration) === null || _b === void 0 ? void 0 : _b.project) && !!((_c = this.firebaseConfiguration) === null || _c === void 0 ? void 0 : _c.env);
    }
}
_cache = new WeakMap(), _getUrl = new WeakMap(), _getKey = new WeakMap();
SdDbService.ɵprov = ɵɵdefineInjectable({ factory: function SdDbService_Factory() { return new SdDbService(ɵɵinject(SdApiService), ɵɵinject(FIREBASE_CONFIG, 8)); }, token: SdDbService, providedIn: "root" });
SdDbService.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
SdDbService.ctorParameters = () => [
    { type: SdApiService },
    { type: undefined, decorators: [{ type: Inject, args: [FIREBASE_CONFIG,] }, { type: Optional }] }
];

/*
 * Public API Surface of superdev-angular-core
 */

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

export { SdDbService };
//# sourceMappingURL=sd-angular-core-db.js.map
