/*-
 * ~~~~~~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;

import java.util.HashMap;
import java.util.Map;

import javax.management.NotCompliantMBeanException;

import org.apache.karaf.bundle.core.BundleInfo;
import org.apache.karaf.bundle.core.BundleState;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.core.management.object.EntaxyRuntimeObjectMBean;
import ru.entaxy.platform.core.management.object.factory.impl.ServiceHelper;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectService;

public abstract class AbstractObjectMBean<T extends EntaxyRuntimeObjectMBean>
        extends AbstractObjectItemMBean<T>
        implements EntaxyRuntimeObjectMBean {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractObjectMBean.class);

    protected EntaxyRuntimeObject entaxyRuntimeObject;

    protected AbstractObjectMBean(Class<T> mbeanInterface, EntaxyRuntimeObject entaxyRuntimeObject)
            throws NotCompliantMBeanException {
        super(mbeanInterface);
        this.entaxyRuntimeObject = entaxyRuntimeObject;
    }

    @Override
    public String getJMXSubQualifierName() {
        if (CommonUtils.isValid(this.jmxSubQualifierName))
            return this.jmxSubQualifierName;
        return EntaxyRuntimeObjectMBean.super.getJMXSubQualifierName();
    }

    @Override
    public String getJMXSubQualifierValue() {
        return entaxyRuntimeObject.getObjectFullId().replace(':', '_');
    }

    @Override
    public long getBundleId() {
        if (entaxyRuntimeObject.getBundleInfo() != null)
            return entaxyRuntimeObject.getBundleInfo().getBundleId();
        return -1;
    }

    @Override
    public String getBundleState() {
        if (getBundleId() < 0)
            return BundleState.Unknown.name();
        BundleInfo bi = ServiceHelper.getInstance().getBundleInfo(getBundleId());
        if (bi == null)
            return BundleState.Unknown.name();
        return bi.getState().name();
    }

    @Override
    public String getBundleSymbolicName() {
        if (entaxyRuntimeObject.isGhost())
            return "";
        if (entaxyRuntimeObject.getContainer() == null)
            return "";
        return entaxyRuntimeObject.getContainer().getName();
    }

    @Override
    public String getId() {
        if (entaxyRuntimeObject != null)
            return entaxyRuntimeObject.getObjectFullId();
        return super.getId();
    }

    @Override
    public void refreshBundleInfo() {
        // TODO Auto-generated method stub
    }

    @Override
    public EntaxyRuntimeObject getRuntimeObject() {
        return this.entaxyRuntimeObject;
    }

    @Override
    public String getName() {
        return entaxyRuntimeObject.getAttributeOrDefault("name", getObjectId()).toString();
    };

    @Override
    public String getObjectId() {
        return this.entaxyRuntimeObject.getId();
    }

    @Override
    public String getObjectType() {
        return this.entaxyRuntimeObject.getType();
    }

    @Override
    public String getObjectFullId() {
        return this.entaxyRuntimeObject.getObjectFullId();
    }

    @Override
    public String getDisplayName() {
        return this.entaxyRuntimeObject.getDisplayName();
    }

    @Override
    public String getObjectLabel() {
        return entaxyRuntimeObject.getAttributeOrDefault("label", "").toString();
    }

    @Override
    public String getFactoryId() {
        return this.entaxyRuntimeObject.getFactoryId();
    }

    @Override
    public String getContainerId() {
        return "" + getBundleId();
    }

    @Override
    public String getScope() {
        return this.entaxyRuntimeObject.getScope();
    }

    @Override
    public String getOwner() {
        return this.entaxyRuntimeObject.getOwner();
    }

    @Override
    public String getRuntimeType() {
        if (entaxyRuntimeObject != null)
            return entaxyRuntimeObject.getType();
        return EntaxyRuntimeObjectMBean.super.getRuntimeType();
    }

    @Override
    public boolean isProvided() {
        if (entaxyRuntimeObject != null)
            return entaxyRuntimeObject.isProvided();
        return false;
    }

    @Override
    public boolean isGhost() {
        if (entaxyRuntimeObject != null)
            return entaxyRuntimeObject.isGhost();
        return true;
    }

    @Override
    public String readConfiguration() {
        if (entaxyRuntimeObject != null)
            return entaxyRuntimeObject.getConfiguration();
        return "";
    }

    @Override
    public Map<String, Map<String, Object>> readExtendedData() {
        try {
            BundleContext bundleContext = FrameworkUtil.getBundle(EntaxyRuntimeObjectService.class).getBundleContext();
            ServiceReference<EntaxyRuntimeObjectService> ref =
                    bundleContext.getServiceReference(EntaxyRuntimeObjectService.class);
            EntaxyRuntimeObjectService objectService = bundleContext.getService(ref);

            Map<String, Map<String, Object>> result = objectService.getExtendedObjectInfo(entaxyRuntimeObject);

            bundleContext.ungetService(ref);
            LOG.debug("Object: " + entaxyRuntimeObject.getObjectFullId() +", readExtendedData: " + result.toString());

            if (result != null)
                return result;

        } catch (Exception e) {
            LOG.error(String.format("Error reading extended data for [%s]", entaxyRuntimeObject.getObjectFullId()), e);
        }
        return new HashMap<>();
    }
}
