"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const datasource_1 = require("../definitions/datasource");
const firestore_1 = require("@google-cloud/firestore");
var Firebase;
(function (Firebase) {
    const SCHEMA = {
        docs: "https://firebase.google.com/docs/firestore/quickstart",
        friendlyName: "Firestore",
        type: "Non-relational",
        description: "Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.",
        datasource: {
            email: {
                type: datasource_1.DatasourceFieldTypes.STRING,
                required: true,
            },
            privateKey: {
                type: datasource_1.DatasourceFieldTypes.STRING,
                required: true,
            },
            projectId: {
                type: datasource_1.DatasourceFieldTypes.STRING,
                required: true,
            },
        },
        query: {
            create: {
                type: datasource_1.QueryTypes.JSON,
            },
            read: {
                type: datasource_1.QueryTypes.JSON,
            },
            update: {
                type: datasource_1.QueryTypes.JSON,
            },
            delete: {
                type: datasource_1.QueryTypes.JSON,
            },
        },
        extra: {
            collection: {
                displayName: "Collection",
                type: datasource_1.DatasourceFieldTypes.STRING,
                required: true,
            },
            filterField: {
                displayName: "Filter field",
                type: datasource_1.DatasourceFieldTypes.STRING,
                required: false,
            },
            filter: {
                displayName: "Filter comparison",
                type: datasource_1.DatasourceFieldTypes.LIST,
                required: false,
                data: {
                    read: [
                        "==",
                        "<",
                        "<=",
                        "!=",
                        ">=",
                        ">",
                        "array-contains",
                        "in",
                        "not-in",
                        "array-contains-any",
                    ],
                },
            },
            filterValue: {
                displayName: "Filter value",
                type: datasource_1.DatasourceFieldTypes.STRING,
                required: false,
            },
        },
    };
    class FirebaseIntegration {
        constructor(config) {
            var _a;
            this.config = config;
            this.client = new firestore_1.Firestore({
                projectId: config.projectId,
                credentials: {
                    client_email: config.email,
                    private_key: (_a = config.privateKey) === null || _a === void 0 ? void 0 : _a.replace(/\\n/g, "\n"),
                },
            });
        }
        create(query) {
            return __awaiter(this, void 0, void 0, function* () {
                try {
                    const documentReference = this.client
                        .collection(query.extra.collection)
                        .doc();
                    yield documentReference.set(Object.assign(Object.assign({}, query.json), { id: documentReference.id }));
                    const snapshot = yield documentReference.get();
                    return snapshot.data();
                }
                catch (err) {
                    console.error("Error writing to Firestore", err);
                    throw err;
                }
            });
        }
        read(query) {
            return __awaiter(this, void 0, void 0, function* () {
                try {
                    let snapshot;
                    const collectionRef = this.client.collection(query.extra.collection);
                    if (query.extra.filterField &&
                        query.extra.filter &&
                        query.extra.filterValue) {
                        snapshot = yield collectionRef
                            .where(query.extra.filterField, query.extra.filter, query.extra.filterValue)
                            .get();
                    }
                    else {
                        snapshot = yield collectionRef.get();
                    }
                    const result = [];
                    snapshot.forEach(doc => result.push(doc.data()));
                    return result;
                }
                catch (err) {
                    console.error("Error querying Firestore", err);
                    throw err;
                }
            });
        }
        update(query) {
            return __awaiter(this, void 0, void 0, function* () {
                try {
                    yield this.client
                        .collection(query.extra.collection)
                        .doc(query.json.id)
                        .update(query.json);
                    return (yield this.client
                        .collection(query.extra.collection)
                        .doc(query.json.id)
                        .get()).data();
                }
                catch (err) {
                    console.error("Error writing to Firestore", err);
                    throw err;
                }
            });
        }
        delete(query) {
            return __awaiter(this, void 0, void 0, function* () {
                try {
                    yield this.client
                        .collection(query.extra.collection)
                        .doc(query.json.id)
                        .delete();
                    return true;
                }
                catch (err) {
                    console.error("Error deleting from Firestore", err);
                    throw err;
                }
            });
        }
    }
    module.exports = {
        schema: SCHEMA,
        integration: FirebaseIntegration,
    };
})(Firebase || (Firebase = {}));
