"use strict";
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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const Logger_1 = require("../../modules/Logger");
const I18n_1 = require("../../modules/I18n");
const WizError_1 = require("../WizError");
const ramda_1 = require("ramda");
const structure_api_1 = require("@ewizardjs/structure-api");
const getDeepCopy_1 = require("../../utils/getDeepCopy");
class Structure {
    constructor(baseDirectory) {
        this.baseDirectory = baseDirectory;
        this.pathToStructure = (0, path_1.resolve)(this.baseDirectory, 'structure.json');
    }
    getSlide(slideId) {
        return __awaiter(this, void 0, void 0, function* () {
            const structure = yield this.getStructure(this.pathToStructure);
            const slide = structure.slides[slideId];
            if (!slide) {
                throw new WizError_1.WizError('SLIDE_NOT_EXISTS', slideId);
            }
            return slide;
        });
    }
    getSlideData(slideId) {
        return __awaiter(this, void 0, void 0, function* () {
            const structure = yield this.getStructure(this.pathToStructure);
            if (!this.slideExists(structure, slideId)) {
                throw new WizError_1.WizError('SLIDE_NOT_EXISTS', slideId);
            }
            return (0, structure_api_1.getFlatSlide)(structure, slideId);
        });
    }
    addSlidesToStructure(slides, chapterId) {
        return this.getStructure(this.pathToStructure)
            .then((structure) => {
            const updatedStructureJson = Object.assign({}, structure);
            slides.forEach((slideId) => {
                updatedStructureJson.slides[slideId] = this.generateSlideTemplate(slideId);
            });
            const updatedSlidesData = getUpdatedSlidesData(updatedStructureJson, slides, chapterId);
            const updatedStructure = (0, structure_api_1.makeStructure)(updatedSlidesData, (0, structure_api_1.getStructureFileVersion)(structure));
            const shakenStructure = removeUnusedFields(updatedStructure);
            return this.updateStructure(shakenStructure);
        });
    }
    addSlidesToChapter(slides, chapterId) {
        return this.getStructure(this.pathToStructure)
            .then((structure) => __awaiter(this, void 0, void 0, function* () {
            if (!this.chapterExists(structure, chapterId)) {
                return this.createChapter(chapterId, slides);
            }
            const updatedStructure = (0, ramda_1.compose)(val => (0, ramda_1.assocPath)(['chapters', chapterId, 'content'], val, structure), ramda_1.uniq, (0, ramda_1.flip)(ramda_1.concat)(slides), (0, ramda_1.pathOr)([], ['chapters', chapterId, 'content']))(structure);
            return this.updateStructure(updatedStructure);
        }));
    }
    addSubslides(subslides, slideId) {
        return this.getStructure(this.pathToStructure)
            .then((structure) => {
            const structureFileVersion = (0, structure_api_1.getStructureFileVersion)(structure);
            if (!this.slideExists(structure, slideId)) {
                throw new WizError_1.WizError('SLIDE_NOT_EXISTS', slideId);
            }
            const chapterId = (0, structure_api_1.getSlide)(structure, slideId).chapter.id;
            const nestedSlides = (0, structure_api_1.getSlides)(structure);
            const nestedSlideIndex = nestedSlides.findIndex(({ id }) => id === slideId);
            if (structureFileVersion === 2 && !chapterId) {
                throw new WizError_1.WizError('NO_CHAPTER_CONTAINS_SLIDE', slideId, slideId);
            }
            nestedSlides[nestedSlideIndex].subslides.push(...getSubslides(subslides, chapterId, structure));
            const nestedSlidesWithoutSubslides = nestedSlides.filter(nestedSlide => !subslides.some(subslideId => subslideId === nestedSlide.id));
            const updatedStructure = (0, structure_api_1.makeStructure)(nestedSlidesWithoutSubslides, structureFileVersion);
            const shakenStructure = removeUnusedFields(updatedStructure);
            return this.updateStructure(shakenStructure);
        });
    }
    createChapter(chapterId, slides) {
        return this.getStructure(this.pathToStructure)
            .then((structure) => __awaiter(this, void 0, void 0, function* () {
            const updatedStructure = Object.assign({}, structure);
            if (!this.chapterExists(updatedStructure, chapterId)) {
                updatedStructure.chapters[chapterId] = this.generateChapterTemplate(chapterId, slides);
                updatedStructure.storyboard.push(chapterId);
                return this.updateStructure(updatedStructure);
            }
            throw new WizError_1.WizError('CHAPTER_EXISTS', chapterId);
        }));
    }
    deleteSlides(removeSlides) {
        return __awaiter(this, void 0, void 0, function* () {
            const structure = yield this.getStructure(this.pathToStructure);
            const structureFileVersion = (0, structure_api_1.getStructureFileVersion)(structure);
            const isntRemoving = (slides) => {
                return (slide) => !slides.includes(slide.id);
            };
            const updatedSlides = (0, structure_api_1.getSlides)(structure)
                .filter(isntRemoving(removeSlides))
                .map(slide => (Object.assign(Object.assign({}, slide), { subslides: slide.subslides.filter(isntRemoving(removeSlides)) })));
            const updatedStructure = (0, structure_api_1.makeStructure)(updatedSlides, structureFileVersion);
            const shakenStructure = removeUnusedFields(updatedStructure);
            return this.updateStructure(shakenStructure);
        });
    }
    save(pathToStructure = this.pathToStructure, structure = this.structure) {
        return __awaiter(this, void 0, void 0, function* () {
            if (structure) {
                return (0, fs_extra_1.writeJSON)(pathToStructure, structure, { spaces: 2 });
            }
        });
    }
    isChapterExists(chapterId) {
        return __awaiter(this, void 0, void 0, function* () {
            const structure = yield this.getStructure(this.pathToStructure);
            return this.chapterExists(structure, chapterId);
        });
    }
    isSlideExists(slideId) {
        return __awaiter(this, void 0, void 0, function* () {
            const structure = yield this.getStructure(this.pathToStructure);
            return this.slideExists(structure, slideId);
        });
    }
    slideExists(structure, slideId) {
        return structure.slides.hasOwnProperty(slideId);
    }
    chapterExists(structure, chapterId) {
        return structure.chapters.hasOwnProperty(chapterId);
    }
    getStructure(path) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.structure) {
                return this.structure;
            }
            return (0, fs_extra_1.readJson)(path);
        });
    }
    generateSlideTemplate(slideId) {
        return {
            name: slideId,
            template: `slides/${slideId}/index.vue`,
        };
    }
    generateChapterTemplate(chapterId, slides = []) {
        return {
            name: chapterId,
            content: slides,
        };
    }
    updateStructure(structure) {
        this.structure = structure;
    }
    convertToStructureV2() {
        return __awaiter(this, void 0, void 0, function* () {
            const structure = yield this.getStructure(this.pathToStructure);
            const structureFileVersion = (0, structure_api_1.getStructureFileVersion)(structure);
            if (structureFileVersion !== 2) {
                const convertedStructure = (0, structure_api_1.convertToStructureV2)(structure);
                this.updateStructure(convertedStructure);
                yield this.save();
                Logger_1.default.info(I18n_1.default.info('STRUCTURE_JSON_UPDATED'));
                return convertedStructure;
            }
            Logger_1.default.info(I18n_1.default.info('STRUCTURE_JSON_HAS_LATEST_VERSION'));
            return structure;
        });
    }
}
exports.default = Structure;
function getUpdatedSlidesData(updatedStructureJson, slides, chapterId) {
    const updatedSlidesData = (0, structure_api_1.getSlides)(updatedStructureJson);
    if (!chapterId) {
        return updatedSlidesData;
    }
    const storyboard = (0, structure_api_1.getStoryboard)(updatedStructureJson);
    const chapterIndex = storyboard.findIndex(chapter => chapter.id === chapterId);
    const chapterType = storyboard[chapterIndex].type;
    slides.map(slideId => {
        const slideIndex = updatedSlidesData.findIndex(slideData => slideData.id === slideId);
        updatedSlidesData[slideIndex].chapter = Object.assign(Object.assign({}, (0, structure_api_1.getChapter)(updatedStructureJson, chapterId)), { storyboardIndex: chapterIndex });
        updatedSlidesData[slideIndex].type = chapterType;
    });
    return updatedSlidesData;
}
function getSubslides(subslides, chapterId, updatedStructure) {
    return subslides.map(subslide => {
        return Object.assign(Object.assign({}, (0, structure_api_1.getSlide)(updatedStructure, subslide)), { chapter: { id: chapterId }, type: structure_api_1.StructureApi.SlideType.Visible });
    });
}
function removeUnusedFields(structure) {
    const updatedStructure = (0, getDeepCopy_1.default)(structure);
    const structureFileVersion = (0, structure_api_1.getStructureFileVersion)(structure);
    if (structureFileVersion === 2 && updatedStructure.archivedSlides.length === 0) {
        delete updatedStructure.archivedSlides;
    }
    return updatedStructure;
}
//# sourceMappingURL=index.js.map