"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveColumns = exports.resolveTables = void 0;
Array.prototype.exactlyOne = function () {
    if (this.length !== 1) {
        return undefined;
    }
    return this[0];
};
class DryRun {
    can(added, removed) {
        return added.length === 0 && removed.length === 0;
    }
    handle(added, _) {
        return { created: added, deleted: [], renamed: [] };
    }
}
// class Fallback implements Handler {
//     can(_: Table[], __: Table[]): boolean {
//         return true
//     }
//     handle(added: Table[], _: Table[]): { created: Table[]; deleted: Table[]; renamed: { from: Table; to: Table; }[]; } {
//         return { created: added, deleted: , renamed: [] }
//     }
// }
class Case1 {
    can(_, removed) {
        return removed.length === 1 && removed[0].name === 'citiess';
    }
    handle(added, removed) {
        return { created: added, deleted: removed, renamed: [] };
    }
}
class Case2 {
    // authOtp, deleted, users -> authOtp renamed, cities added, deleted deleted
    can(_, removed) {
        return removed.length === 3 && removed[0].name === 'auth_otp';
    }
    handle(added, removed) {
        return { created: added.slice(1), deleted: removed.slice(1), renamed: [{ from: removed[0], to: added[0] }] };
    }
}
const handlers = [];
handlers.push(new Case1());
handlers.push(new Case2());
handlers.push(new DryRun());
const resolveTables = (added, removed) => {
    const handler = handlers.filter(it => {
        return it.can(added, removed);
    }).exactlyOne();
    if (!handler) {
        console.log('added', added.map(it => it.name).join());
        console.log('removed', removed.map(it => it.name).join());
        throw new Error("No handler");
    }
    console.log(`Simluated by ${handler.constructor.name}`);
    return handler.handle(added, removed);
};
exports.resolveTables = resolveTables;
class LehaColumnsHandler {
    can(tableName, _, __) {
        return tableName === 'users';
    }
    handle(tableName, added, removed) {
        return { tableName, created: [], deleted: [], renamed: [{ from: removed[0], to: added[0] }] };
    }
}
class DryRunColumnsHandler {
    can(tableName, _, __) {
        return true;
    }
    handle(tableName, added, removed) {
        return { tableName, created: added, deleted: removed, renamed: [] };
    }
}
class V1V2AuthOtpColumnsHandler {
    can(tableName, _, __) {
        return tableName === 'auth_otp';
    }
    handle(tableName, added, removed) {
        const phonePrev = removed.filter((it) => it.name === 'phone')[0];
        const phoneNew = added.filter((it) => it.name === 'phone1')[0];
        const newAdded = added.filter((it => it.name !== 'phone1'));
        const newRemoved = removed.filter((it => it.name !== 'phone'));
        return { tableName, created: newAdded, deleted: newRemoved, renamed: [{ from: phonePrev, to: phoneNew }] };
    }
}
const columnsHandlers = [];
columnsHandlers.push(new V1V2AuthOtpColumnsHandler());
columnsHandlers.push(new LehaColumnsHandler());
columnsHandlers.push(new DryRunColumnsHandler());
const resolveColumns = (tableName, added, removed) => {
    const handler = columnsHandlers.filter(it => {
        return it.can(tableName, added, removed);
    })[0];
    if (!handler) {
        console.log('added', added.map(it => it.name).join());
        console.log('removed', removed.map(it => it.name).join());
        throw new Error("No columns handler for table: " + tableName);
    }
    console.log(`${tableName} columns simluated by ${handler.constructor.name}`);
    return handler.handle(tableName, added, removed);
};
exports.resolveColumns = resolveColumns;
//# sourceMappingURL=simulator.js.map