"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.promptColumnsConflicts = exports.promptTablesConflicts = exports.task = void 0;
const xstate_1 = require("xstate");
const resolveTablesMachine_1 = __importDefault(require("../machines/resolveTablesMachine"));
const resolveColumnsMachine_1 = __importDefault(require("../machines/resolveColumnsMachine"));
const formatDataForTable_1 = __importDefault(require("../utils/formatDataForTable"));
const loading = require('loading-cli');
const { Select, Confirm } = require('enquirer');
const Table = require('cli-table');
const actions = ['Renamed', 'Deleted'];
const bold = '\x1b[1m';
const red = '\u001B[31m';
const blue = '\u001B[34m';
const reset = '\u001B[0m';
const getElementIndexByName = (array, elementName) => array.findIndex(({ name }) => name === elementName);
const clearLine = () => {
    process.stdout.moveCursor(0, -1);
    process.stdout.clearLine(1);
};
const task = async (titleStr, func) => {
    const progress = loading({
        frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],
        text: `${bold}${titleStr}`,
    }).start();
    try {
        const result = await func({
            setTitle: (title) => { progress.text = `${bold}${title}`; },
            setError: (error) => { progress.fail(error.message); },
        });
        progress.succeed();
        return result;
    }
    catch (error) {
        progress.fail(`${bold}${error.message}`);
        throw Error(error);
    }
};
exports.task = task;
const promptTablesConflicts = ({ missingTables: m, newTables: n }) => new Promise((resolve) => {
    const resolveTablesMachine = resolveTablesMachine_1.default({ missingTables: m, newTables: n });
    const service = xstate_1.interpret(resolveTablesMachine).start();
    service.subscribe(async (state) => {
        try {
            const { missingItemIndex, newItemIndex, newTables, missingTables, createdTables, renamedTables, deletedTables, } = state.context;
            if (state.matches('idle')) {
                service.send({ type: 'NEXT' });
            }
            if (state.changed && state.matches('table')) {
                const tableName = await new Select({
                    name: 'tableName',
                    message: 'Chose missing table:',
                    choices: missingTables.map(({ name }) => name),
                }).run();
                clearLine();
                service.send({ type: 'CHOICE_ITEM', itemIndex: getElementIndexByName(missingTables, tableName) });
            }
            if (state.changed && state.matches('action.actionChoice')) {
                const actionName = await new Select({
                    name: 'tableName',
                    message: `Table "${missingTables[missingItemIndex].name}" was:`,
                    choices: actions,
                }).run();
                clearLine();
                service.send({ type: actionName.toUpperCase() });
            }
            if (state.changed && state.matches('confirmationDelete')) {
                const confirmation = await new Confirm({
                    name: 'confirm',
                    message: 'Are you sure?',
                    initial: true,
                }).run();
                clearLine();
                if (confirmation)
                    console.log(`${bold}Deleted "${missingTables[missingItemIndex].name}" table, ${red}all data will be lost!`);
                service.send({ type: confirmation ? 'CONFIRM' : 'CANCEL' });
            }
            if (state.changed && state.matches('confirmationRename')) {
                const confirmation = await new Confirm({
                    name: 'confirm',
                    message: 'Are you sure?',
                    initial: true,
                }).run();
                clearLine();
                if (confirmation)
                    console.log(`${bold}Renamed "${missingTables[missingItemIndex].name}" -> "${newTables[newItemIndex].name}"`);
                service.send({ type: confirmation ? 'CONFIRM' : 'CANCEL' });
            }
            if (state.changed && state.matches('action.rename')) {
                const tableName = await new Select({
                    name: 'tableName',
                    message: `Table "${missingTables[missingItemIndex]?.name}" was renamed to:`,
                    choices: newTables.map(({ name }) => name),
                }).run();
                clearLine();
                service.send({ type: 'CHOICE_NEW_ITEM', itemIndex: getElementIndexByName(newTables, tableName) });
            }
            if (state.changed && state.matches('done')) {
                if (createdTables.length || deletedTables.length || renamedTables.length) {
                    const table = new Table({
                        head: [`${blue}Created`, `${blue}Renamed`, `${blue}Deleted`],
                        rows: formatDataForTable_1.default(createdTables, renamedTables, deletedTables)
                    });
                    console.log(`${reset}${bold}Tables:`);
                    console.log(table.toString());
                }
                resolve({
                    created: createdTables,
                    deleted: deletedTables,
                    renamed: renamedTables,
                });
                service.stop();
            }
        }
        catch (e) {
            console.error(e);
        }
    });
});
exports.promptTablesConflicts = promptTablesConflicts;
const promptColumnsConflicts = (props) => new Promise((resolve) => {
    const resolveColumnsMachine = resolveColumnsMachine_1.default(props);
    const service = xstate_1.interpret(resolveColumnsMachine).start();
    service.subscribe(async (state) => {
        try {
            const { tableName, addedColumns, deletedColumns, missingItemIndex, newItemIndex, created, renamed, deleted, } = state.context;
            if (state.matches('idle')) {
                service.send({ type: 'NEXT' });
            }
            if (state.changed && state.matches('table')) {
                const columnName = await new Select({
                    name: 'columnName',
                    message: `Table "${tableName}" missing columns:`,
                    choices: deletedColumns.map(({ name }) => name),
                }).run();
                clearLine();
                service.send({ type: 'CHOICE_ITEM', itemIndex: getElementIndexByName(deletedColumns, columnName) });
            }
            if (state.changed && state.matches('action.actionChoice')) {
                const actionName = await new Select({
                    name: 'tableName',
                    message: `Column "${deletedColumns[missingItemIndex].name}" was:`,
                    choices: actions,
                }).run();
                clearLine();
                service.send({ type: actionName.toUpperCase() });
            }
            if (state.changed && state.matches('confirmationDelete')) {
                const confirmation = await new Confirm({
                    name: 'confirm',
                    message: 'Are you sure?',
                    initial: true,
                }).run();
                clearLine();
                if (confirmation)
                    console.log(`${bold}Deleted column "${deletedColumns[missingItemIndex].name}" from "${tableName}" table, ${red}all data will be lost!`);
                service.send({ type: confirmation ? 'CONFIRM' : 'CANCEL' });
            }
            if (state.changed && state.matches('confirmationRename')) {
                const confirmation = await new Confirm({
                    name: 'confirm',
                    message: 'Are you sure?',
                    initial: true,
                }).run();
                clearLine();
                if (confirmation)
                    console.log(`${bold}Renamed "${deletedColumns[missingItemIndex].name} -> ${addedColumns[newItemIndex].name}" in "${tableName}" table`);
                service.send({ type: confirmation ? 'CONFIRM' : 'CANCEL' });
            }
            if (state.changed && state.matches('action.rename')) {
                const columnName = await new Select({
                    name: 'tableName',
                    message: `Column "${deletedColumns[missingItemIndex]?.name}" was renamed to:`,
                    choices: addedColumns.map(({ name }) => name),
                }).run();
                clearLine();
                service.send({ type: 'CHOICE_NEW_ITEM', itemIndex: getElementIndexByName(addedColumns, columnName) });
            }
            if (state.changed && state.matches('done')) {
                if (created.length || deleted.length || renamed.length) {
                    const table = new Table({
                        head: [`${blue}Created`, `${blue}Renamed`, `${blue}Deleted`],
                        rows: formatDataForTable_1.default(created, renamed, deleted)
                    });
                    console.log(`${reset}${bold}Table "${tableName}" columns:`);
                    console.log(table.toString());
                }
                resolve({
                    created,
                    deleted,
                    renamed,
                });
                service.stop();
            }
        }
        catch (e) {
            console.error(e);
        }
    });
});
exports.promptColumnsConflicts = promptColumnsConflicts;
//# sourceMappingURL=index.js.map