"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const crypto_1 = tslib_1.__importDefault(require("crypto"));
const shortid_1 = tslib_1.__importDefault(require("shortid"));
const faker_1 = tslib_1.__importDefault(require("faker"));
const lodash_clonedeep_1 = tslib_1.__importDefault(require("lodash.clonedeep"));
const editure_constants_1 = require("editure-constants");
const index_1 = require("../index");
const nodes_1 = require("../nodes");
function randomHex(digits = 32) {
    return crypto_1.default.randomBytes(digits).toString('hex');
}
function getFakeExplain() {
    const numOfParagraphs = faker_1.default.random.number({ min: 1, max: 5 });
    return {
        type: 'explain',
        fixed: true,
        children: ' '
            .repeat(numOfParagraphs)
            .split('')
            .map(() => ({
            type: editure_constants_1.PARAGRAPH,
            children: [{ text: faker_1.default.lorem.paragraph() }],
        })),
    };
}
function getFakeStepTitle(commit) {
    return {
        type: 'heading-two',
        fixed: true,
        id: shortid_1.default.generate(),
        commit,
        children: [{ text: faker_1.default.lorem.sentence() }],
    };
}
function getFakeDiffBlock(commit, file) {
    return {
        type: 'diff-block',
        file,
        commit,
        children: nodes_1.getEmptyChildren(),
    };
}
function getFakeFile(commit) {
    const file = faker_1.default.lorem.word();
    return {
        type: 'file',
        display: true,
        file,
        children: [
            nodes_1.getEmptyExplain(),
            getFakeDiffBlock(commit, file),
            nodes_1.getEmptyExplain(),
        ],
    };
}
function getFakeFiles(commit, num) {
    const numOfFiles = num || faker_1.default.random.number({ min: 1, max: 5 });
    return ' '
        .repeat(numOfFiles)
        .split('')
        .map(() => getFakeFile(commit));
}
function getFakeStep() {
    const commit = randomHex();
    return {
        type: 'step',
        id: shortid_1.default.generate(),
        articleId: shortid_1.default.generate(),
        commit,
        children: [
            getFakeStepTitle(commit),
            nodes_1.getEmptyExplain(),
            ...getFakeFiles(commit),
            nodes_1.getEmptyExplain(),
        ],
    };
}
function getFakeSteps(num) {
    return ' '
        .repeat(num)
        .split('')
        .map(() => getFakeStep());
}
function populateSteps(steps) {
    return steps.map((step) => {
        const clonedStep = lodash_clonedeep_1.default(step);
        for (let i = 0; i < clonedStep.children.length; i++) {
            const child = clonedStep.children[i];
            if (child.type === 'explain') {
                clonedStep.children[i] = getFakeExplain();
            }
            else if (child.type === 'file') {
                child.children[0] = getFakeExplain();
                child.children[2] = getFakeExplain();
            }
        }
        return clonedStep;
    });
}
describe('utils/index', () => {
    describe('isCommitEqual', () => {
        const hashA = randomHex();
        const hashB = randomHex();
        test('commits with exactly the same hash', () => {
            expect(index_1.isCommitEqual(hashA, hashA)).toBe(true);
        });
        test('commits with different hashes', () => {
            expect(index_1.isCommitEqual(hashA, hashB)).toBe(false);
        });
        test('same commit with different digits', () => {
            expect(index_1.isCommitEqual(hashA, hashA.slice(0, 8))).toBe(true);
            expect(index_1.isCommitEqual(hashB.slice(0, 8), hashB)).toBe(true);
        });
    });
    describe('mergeSteps', () => {
        test('add a new step', () => {
            const [step1, step2, step3] = getFakeSteps(3);
            const [pStep1, pStep2] = populateSteps([step1, step2]);
            const prevSteps = [pStep1, pStep2];
            const newSteps = [step1, step2, step3];
            const mergedSteps = index_1.mergeSteps(prevSteps, newSteps);
            expect(mergedSteps).toStrictEqual([pStep1, pStep2, step3]);
        });
        test('add multiple new steps', () => {
            const [step1, step2, step3] = getFakeSteps(3);
            const [pStep1] = populateSteps([step1]);
            const prevSteps = [pStep1];
            const newSteps = [step1, step2, step3];
            const mergedSteps = index_1.mergeSteps(prevSteps, newSteps);
            expect(mergedSteps).toStrictEqual([pStep1, step2, step3]);
        });
        test('last commit outdated', () => {
            const [step1, step2, step3] = getFakeSteps(3);
            const [pStep1, pStep2] = populateSteps([step1, step2]);
            const prevSteps = [pStep1, pStep2];
            const newSteps = [step1, step3];
            const mergedSteps = index_1.mergeSteps(prevSteps, newSteps);
            expect(mergedSteps).toStrictEqual([
                pStep1,
                step3,
                Object.assign(Object.assign({}, pStep2), { outdated: true }),
            ]);
        });
        test('all commits outdated', () => {
            const [step1, step2, step3, step4] = getFakeSteps(4);
            const [pStep1, pStep2] = populateSteps([step1, step2]);
            const prevSteps = [pStep1, pStep2];
            const newSteps = [step3, step4];
            const mergedSteps = index_1.mergeSteps(prevSteps, newSteps);
            expect(mergedSteps).toStrictEqual([
                step3,
                step4,
                Object.assign(Object.assign({}, pStep1), { outdated: true }),
                Object.assign(Object.assign({}, pStep2), { outdated: true }),
            ]);
        });
    });
    describe('isInitialized', () => { });
});
