
const collection = 'scenarios';

/**
 * Scenarios manager class, контролен клас за управление на игрови сценарии
 */
class ScenariosManager{
    name = 'scenario';

    /**
     * Class initializer, инициализация
     * @param {App} app Class initializer, основна апликация
     */
    init(app){
        const {db, am} = app;

        /**
         * Creates a new scenario, създаване на нов сценарий
         * @param {Context} ctx Request context, контекст на заявката
         * @param {Scenario} data the scenario, данни за сценария
         */
        this.create = async function(ctx, data){
            data.id = await db.getId(collection);
            await db.create(collection, data);
            return data;
        }

        /**
         * Reads scenario by ID, извличане на сценарий по подаден идентификатор
         * @param {Number} id scenario ID, идентификатор
         * @returns {Scenario}
         */
        this.read = async function(id){
            id = parseInt(id);
            return await db.get(collection, {id});
        }

        /**
         * Updates scenario, обновяване на сценарий
         * @param {Context} ctx Request context, контекст на заявката
         * @param {Scenario} data the scenario
         */
        this.update = async function(ctx, data){
            data.id = parseInt(data.id);
            let object = await this.read(data.id);
            await am.addToHistory(object, collection, 'update');
            data = Object.assign(object, data);
            await db.update(collection, {id: data.id}, data);
            return data;
        }

        /**
         * Removes scenario by ID, изтриване на сценарий по подаден идентификатор
         * @param {Number} id scenario ID, идентификатор на сценарий
         */
        this.remove = async function(id){
            id = parseInt(id);
            await am.addToHistory(id, collection, 'delete');
            await db.remove(collection, {id});
        }

        /**
         * Returns a set of scenarios by given criteria, търсене в игровите сценарии по зададени критерии
         * @param {Query} query criteria, критерии - заявка към базата от данни
         * @returns {Scenario[]}
         */
        this.list = async function(query = {}){
            return await db.list(collection, {
                query,
                project: { name:1, id:1, sceneThumb: '$scenes.data.environment'}
            });
        }
        
    }

    /**
     * Class starter, стартиране на класа
     * @param {App} app The application, основна апликация
     */
    async start(app){

    }
}

/**
 * Scenario entity, обект - сценарий
 */
class Scenario {
    /**
     * Scenario name, име на сценария
     * @type {string}
     */
    name = null;

    /**
     * Scenario levels, нива
     * @type {Level[]}
     */
    levels = [];
}

/**
 * Game scenario level, ниво на игрови сценарий
 */
class Level {
    /**
     * Level name, име на нивото
     * @type {string}
     */
    name = null;

    /**
     * Active objects, активни обекти
     * @type {LevelObject[]}
     */
    activeObjects = []
}

/**
 * Game object associated to a level, игрови обекти, асоциирани към дадено ниво
 */
class LevelObject {
    /**
     * Associated game object, асоцииран игрови обект
     * @type {GameObject}
     */
    gameObject = null;

    /**
     * Available actions, възможни действия
     * @type {GameAction}
     */
    actions = []
}

/**
 * Action associated to game object, действие, асоциирано към игрови обект
 */
class GameAction {
    /**
     * Action name, име на действието
     * @type {string}
     */
    name = null;

    /**
     * Action description, описание на действието
     * @type {string}
     */
    description = null;

    /**
     * Associated inventory item, асоцииран инвентар
     * @type {InventoryItem}
     */
    inventoryItem = null;

    /**
     * Available outcomes from the action, възможни резултати от действието
     * @type {GameActionResult}
     */
    results = []
}

/**
 * Result associated to game action, резултати, асоциирани към дадено игрово действие
 */
class GameActionResult{

    /**
     * Applied rules to the specific result, приложени игрови правила към даден резултат
     * @type Rule[]
     */
    rules = []

    /**
     * Result name, име на резултата
     * @type string
     */
    name = null;

    /**
     * Result description, описание на резултата
     * @type string
     */
    description = null;
}

/**
 * Inventory item required to perform specific action, инвентар необходим за изпълнението на определено действие
 */
class InventoryItem {
    /**
     * Inventory item name, име на елемент от инвентара
     * @type string
     */
    name = null;

    /**
     * Inventory item description, описание на елемент от инвентара
     * @type string
     */
    description = null;
}

export { ScenariosManager }