/*-
 * ~~~~~~licensing~~~~~~
 * secure-vault-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.security.vault.management.impl;

import java.util.List;

import javax.management.NotCompliantMBeanException;

import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;

import ru.entaxy.esb.platform.base.management.core.Qualifier;
import ru.entaxy.esb.platform.base.management.core.api.EntaxyRuntimeTyped;
import ru.entaxy.platform.core.management.object.ObjectMBean;
import ru.entaxy.platform.core.management.object.factory.AbstractObjectMBean;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.security.vault.management.SecureVaultMBean;
import ru.entaxy.security.vault.management.SecureVaultsMBean;
import ru.entaxy.security.vault.runtime.EntaxyVault;

@EntaxyRuntimeTyped(name = SecureVaultsMBean.VAULT_RUNTIME_TYPE)
@ObjectMBean(subQualifierName = SecureVaultMBean.SUBQUALIFIER_KEY)
public class SecureVaultMBeanImpl<T extends SecureVaultMBean> extends AbstractObjectMBean<T>
        implements SecureVaultMBean {

    public SecureVaultMBeanImpl(EntaxyRuntimeObject entaxyRuntimeObject)
            throws NotCompliantMBeanException {
        super((Class<T>) SecureVaultMBean.class, entaxyRuntimeObject);
    }

    protected SecureVaultMBeanImpl(Class<T> mbeanInterface, EntaxyRuntimeObject entaxyRuntimeObject)
            throws NotCompliantMBeanException {
        super(mbeanInterface, entaxyRuntimeObject);
    }

    @Override
    public Qualifier getJMXQualifier() {
        return SecureVaultsMBean.QUALIFIER.qualifier(SecureVaultMBean.SUBQUALIFIER_KEY, getObjectId());
    }

    @Override
    public String getJMXSubQualifier() {
        return SecureVaultsMBean.SUBQUALIFIER.concat(",").concat(SecureVaultMBean.SUBQUALIFIER_KEY).concat("=")
                .concat(getObjectId());
    }

    @Override
    public String readValue(String alias) throws IllegalArgumentException {
        VaultHolder holder = getHolder();
        String value = holder.entaxyVault.getData(alias);
        holder.unget();
        return value;
    }

    @Override
    public void removeValue(String alias) throws IllegalArgumentException {
        VaultHolder holder = getHolder();
        holder.entaxyVault.removeData(alias);
        holder.unget();
    }

    @Override
    public void writeValue(String alias, String value) throws IllegalArgumentException {
        VaultHolder holder = getHolder();
        holder.entaxyVault.setData(alias, value);
        holder.unget();
    }

    @Override
    public List<String> listAliases() throws IllegalArgumentException {
        VaultHolder holder = getHolder();
        List<String> result = holder.entaxyVault.getAliases();
        holder.unget();
        return result;
    }

    protected VaultHolder getHolder() throws IllegalArgumentException {
        VaultHolder holder = new VaultHolder();
        ServiceReference<?>[] referenses = null;
        try {
            referenses = FrameworkUtil.getBundle(SecureVaultMBean.class).getBundleContext()
                    .getAllServiceReferences(EntaxyVault.class.getName(),
                            "(name=" + this.getRuntimeObject().getId() + ")");
        } catch (Exception ignore) {
            // NOOP
        }
        if (referenses == null || referenses.length == 0)
            throw new IllegalArgumentException(String.format("Vault [%s] not available",
                    SecureVaultMBeanImpl.this.getRuntimeObject().getId()));
        holder.reference = (ServiceReference<EntaxyVault>) referenses[0];
        try {
            holder.entaxyVault =
                    FrameworkUtil.getBundle(SecureVaultMBean.class).getBundleContext().getService(holder.reference);
        } catch (Exception e) {
            throw new IllegalArgumentException(String.format("Vault [%s] not available",
                    SecureVaultMBeanImpl.this.getRuntimeObject().getId()));
        }

        if (holder.entaxyVault == null)
            throw new IllegalArgumentException(String.format("Vault [%s] not available",
                    SecureVaultMBeanImpl.this.getRuntimeObject().getId()));

        return holder;
    }


    protected class VaultHolder {

        EntaxyVault entaxyVault;
        ServiceReference<EntaxyVault> reference;

        public void unget() {
            FrameworkUtil.getBundle(SecureVaultMBean.class).getBundleContext().ungetService(reference);
        }
    }
}
