/*-
 * ~~~~~~licensing~~~~~~
 * object-management
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.platform.core.management.object.factory.impl;

import javax.management.NotCompliantMBeanException;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.core.management.object.ContainerMBean;
import ru.entaxy.platform.core.management.object.EntaxyRuntimeObjectMBeanFactory;
import ru.entaxy.platform.core.management.object.factory.AbstractObjectContainerMBean;
import ru.entaxy.platform.core.management.object.factory.ObjectsContainerMBean;
import ru.entaxy.platform.core.management.object.impl.EntaxyRuntimeObjectMBeanManager;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectManager.OperationResult;

import java.util.stream.Collectors;

@ContainerMBean(id = "objects", subQualifierValue = EntaxyRuntimeObjectMBeanFactory.JMX_DEFAULT_CATEGORY)
public class ObjectsContainerMBeanImpl extends AbstractObjectContainerMBean<ObjectsContainerMBean>
        implements ObjectsContainerMBean {

    protected EntaxyRuntimeObjectMBeanManager manager;

    protected ObjectsContainerMBeanImpl() throws NotCompliantMBeanException {
        super(ObjectsContainerMBean.class);
    }

    @Override
    public void refresh() {
        manager.refresh();
    }

    @Override
    public String startBundle(String idOrName, String runtimeType, boolean forced, boolean soft) throws Exception {
        if (ServiceHelper.getInstance() == null) {
            throw new IllegalStateException("Service helper is not initialized");
        }

        String objectFullId = ServiceHelper.getInstance()
                .entaxyObjectService.findObject(idOrName, runtimeType).getObjectFullId();

        OperationResult result;

        if (forced) {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.startForced(objectFullId);
        } else if (soft) {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.startSoft(objectFullId);
        } else {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.start(objectFullId);
        }

        return getOutput(result);
    }

    @Override
    public String stopBundle(String idOrName, String runtimeType, boolean forced, boolean soft) throws Exception {
        if (ServiceHelper.getInstance() == null) {
            throw new IllegalStateException("Service helper is not initialized");
        }

        String objectFullId = ServiceHelper.getInstance()
                .entaxyObjectService.findObject(idOrName, runtimeType).getObjectFullId();

        OperationResult result;

        if (forced) {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.stopForced(objectFullId);
        } else if (soft) {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.stopSoft(objectFullId);
        } else {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.stop(objectFullId);
        }

        return getOutput(result);
    }

    @Override
    public String uninstallBundle(String idOrName, String runtimeType, boolean forced, boolean soft) throws Exception {
        if (ServiceHelper.getInstance() == null) {
            throw new IllegalStateException("Service helper is not initialized");
        }

        String objectFullId = ServiceHelper.getInstance()
                .entaxyObjectService.findObject(idOrName, runtimeType).getObjectFullId();

        OperationResult result;

        if (forced) {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.uninstallForced(objectFullId);
        } else if (soft) {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.uninstallSoft(objectFullId);
        } else {
            result = ServiceHelper.getInstance().entaxyRuntimeObjectManager.uninstall(objectFullId);
        }

        return getOutput(result);
    }

    private String getOutput(OperationResult result) {
        JsonObject jsonObject = new JsonObject();

        jsonObject.addProperty("result", result.getResult().name());
        if (!result.getAffected().isEmpty()) {
            JsonArray affectedArray = new JsonArray();
            for (String key : result.getAffected().keySet()) {
                JsonObject affected = new JsonObject();
                affected.addProperty("objectId", key);
                affected.addProperty("action", result.getAffected().get(key).name());
                affectedArray.add(affected);
            }
            jsonObject.addProperty("affected", affectedArray.toString());
        }
        if (CommonUtils.isValid(result.getMessage())) {
            jsonObject.addProperty("message", result.getMessage());
        }

        return jsonObject.toString();
    }

    public String findObjects(String osgiFilter) throws Exception {
        return JSONUtils.GSON.toJson(manager.findObjects(osgiFilter).stream().map(object -> {
            return object.getObjectFullId();
        }).collect(Collectors.toList()));
    }
}
