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());
    });
};
import { deleteMutation, generateSerial, insertMutation, updateMutation } from "../gql";
export class SerialTransitionsBuilder {
    constructor(options) {
        var _a, _b;
        this.deep = options.deep;
        this.serialActions = [];
        this.defaultTable = (_a = options.defaultTable) !== null && _a !== void 0 ? _a : 'links';
        this.executeOptions = (_b = options.executeOptions) !== null && _b !== void 0 ? _b : {};
    }
    append(options) {
        this.appendMultiple([options]);
        return this;
    }
    appendMultiple(options) {
        var _a;
        for (const optionsItem of options) {
            const { table = this.defaultTable, transition } = optionsItem;
            const transitionType = this.getTransitionType(transition);
            const index = this.serialActions.length;
            let serialAction;
            switch (transitionType) {
                case 'insert':
                    serialAction = {
                        mutation: insertMutation(table, { objects: transition[1] }),
                        index,
                        transitionType,
                        table
                    };
                    break;
                case 'update':
                    serialAction = {
                        mutation: updateMutation(table, { exp: transition[0], value: transition[1] }),
                        index,
                        transitionType,
                        table
                    };
                    break;
                case 'delete':
                    serialAction = {
                        mutation: deleteMutation(table, { exp: transition[0] }),
                        index,
                        transitionType,
                        table
                    };
                default:
                    throw new Error('Invalid transition type. If you want to insert link - the first element must be null and the second must be link. If you want to update link - the first and second elements must be links. If you want to delete link - the first element must be link and second must be null');
            }
            serialAction.alias = (_a = optionsItem.alias) !== null && _a !== void 0 ? _a : `${transitionType}_${table}_${index}`;
            this.serialActions.push(serialAction);
        }
        return this;
    }
    clear() {
        this.serialActions = [];
        return this;
    }
    execute(options = this.executeOptions) {
        return __awaiter(this, void 0, void 0, function* () {
            const result = yield this.deep.apolloClient.mutate(generateSerial(Object.assign({ actions: this.serialActions.map(serialAction => serialAction.mutation) }, options)));
            const data = result.data;
            for (const serialAction of this.serialActions) {
                const oldKey = `m${serialAction.index}`;
                const newValue = Object.assign(Object.assign({}, data[oldKey].returning), { index: serialAction.index });
                data[serialAction.alias] = newValue;
                data[serialAction.index] = newValue;
                delete data[oldKey];
            }
            return Object.assign(Object.assign({}, result), { data });
        });
    }
    actions() {
        return this.serialActions;
    }
    getTransitionType(transition) {
        if (transition[0] === null) {
            return 'insert';
        }
        else if (transition[1] === null) {
            return 'delete';
        }
        else if (transition[0] !== null && transition[1] !== null) {
            return 'update';
        }
        else {
            throw new Error('Invalid transition');
        }
    }
    setDefaultTable(table) {
        this.defaultTable = table;
        return this;
    }
    getDefaultTable() {
        return this.defaultTable;
    }
    setDeep(deep) {
        this.deep = deep;
        return this;
    }
    getDeep() {
        return this.deep;
    }
    setExecuteOptions(options) {
        this.executeOptions = options;
        return this;
    }
    getExecuteOptions() {
        return this.executeOptions;
    }
}
//# sourceMappingURL=serial-transitions-builder.js.map