"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
const path_1 = tslib_1.__importDefault(require("path"));
const logger_1 = tslib_1.__importDefault(require("./logger"));
const git_1 = require("./git");
const constants_1 = require("../constants");
const assets_1 = require("./assets");
exports.collectionPath = path_1.default.join(process.env.TUTURE_PATH || process.cwd(), constants_1.TUTURE_ROOT, constants_1.COLLECTION_PATH);
exports.collectionCheckpoint = path_1.default.join(process.env.TUTURE_PATH || process.cwd(), constants_1.TUTURE_ROOT, constants_1.COLLECTION_CHECKPOINT);
exports.collectionVcsPath = path_1.default.join(process.env.TUTURE_PATH || process.cwd(), constants_1.TUTURE_VCS_ROOT, constants_1.COLLECTION_PATH);
function hasCollectionChangedSinceCheckpoint() {
    if (!fs_extra_1.default.existsSync(exports.collectionCheckpoint)) {
        return true;
    }
    return !fs_extra_1.default
        .readFileSync(exports.collectionPath)
        .equals(fs_extra_1.default.readFileSync(exports.collectionCheckpoint));
}
exports.hasCollectionChangedSinceCheckpoint = hasCollectionChangedSinceCheckpoint;
/**
 * Whether the local tuture branch exists.
 */
async function hasLocalTutureBranch() {
    return (await git_1.git.branchLocal()).all.includes(constants_1.TUTURE_BRANCH);
}
exports.hasLocalTutureBranch = hasLocalTutureBranch;
/**
 * Whether the remote tuture branch exists.
 */
async function hasRemoteTutureBranch() {
    const remote = await git_1.git.remote([]);
    if (!remote) {
        logger_1.default.log('warning', 'No remote found for this repository.');
        return false;
    }
    const branchExists = async (branch) => {
        const { all } = await git_1.git.branch({ '-a': true });
        return all.includes(remoteBranch);
    };
    const remoteBranch = `remotes/${remote.trim()}/${constants_1.TUTURE_BRANCH}`;
    // Trying to update remote branches (time-consuming).
    await git_1.git.remote(['update', '--prune']);
    return await branchExists(remoteBranch);
}
exports.hasRemoteTutureBranch = hasRemoteTutureBranch;
/**
 * Load collection.
 */
function loadCollection() {
    let rawCollection = fs_extra_1.default.readFileSync(exports.collectionPath).toString();
    const assetsTable = assets_1.loadAssetsTable();
    // COMPAT: convert all asset paths
    assetsTable.forEach((asset) => {
        const { localPath, hostingUri } = asset;
        if (hostingUri) {
            rawCollection = rawCollection.replace(new RegExp(localPath, 'g'), hostingUri);
        }
    });
    const collection = JSON.parse(rawCollection);
    // COMPAT: convert hiddenLines field
    if (collection.version !== 'v1') {
        const convertHiddenLines = (hiddenLines) => {
            const rangeGroups = [];
            let startNumber = null;
            for (let i = 0; i < hiddenLines.length; i++) {
                const prev = hiddenLines[i - 1];
                const current = hiddenLines[i];
                const next = hiddenLines[i + 1];
                if (current !== prev + 1 && current !== next - 1) {
                    rangeGroups.push([current, current]);
                }
                else if (current !== prev + 1) {
                    startNumber = hiddenLines[i];
                }
                else if (current + 1 !== next) {
                    rangeGroups.push([startNumber, hiddenLines[i]]);
                }
            }
            return rangeGroups;
        };
        for (const step of collection.steps) {
            for (const node of step.children) {
                if (node.type === 'file') {
                    const diffBlock = node.children[1];
                    if (diffBlock.hiddenLines) {
                        diffBlock.hiddenLines = convertHiddenLines(diffBlock.hiddenLines);
                    }
                }
            }
        }
        collection.version = 'v1';
    }
    return collection;
}
exports.loadCollection = loadCollection;
/**
 * Save the entire collection back to workspace.
 */
function saveCollection(collection) {
    fs_extra_1.default.writeFileSync(exports.collectionPath, JSON.stringify(collection, null, 2));
}
exports.saveCollection = saveCollection;
/**
 * Fetch tuture branch from remote.
 */
async function initializeTutureBranch() {
    const { all: allBranches } = await git_1.git.branch({ '-a': true });
    // Already exists.
    if (allBranches.includes(constants_1.TUTURE_BRANCH)) {
        return;
    }
    const remoteBranchIndex = allBranches
        .map((branch) => branch.split('/').slice(-1)[0])
        .indexOf(constants_1.TUTURE_BRANCH);
    if (remoteBranchIndex < 0) {
        await git_1.git.branch([constants_1.TUTURE_BRANCH]);
        logger_1.default.log('info', 'New tuture branch has been created.');
    }
    else {
        const [_, remote, branch] = allBranches[remoteBranchIndex].split('/');
        await git_1.git.fetch(remote, branch);
        logger_1.default.log('success', 'Remote tuture branch has been fetched.');
    }
}
exports.initializeTutureBranch = initializeTutureBranch;
function saveCheckpoint() {
    // Copy the last committed file.
    fs_extra_1.default.copySync(exports.collectionPath, exports.collectionCheckpoint, { overwrite: true });
}
exports.saveCheckpoint = saveCheckpoint;
