/*-
 * ~~~~~~licensing~~~~~~
 * base-support
 * ==========
 * 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.base.support.osgi.feature;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.karaf.bundle.core.BundleService;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
import org.osgi.framework.Bundle;
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;

public class FeaturesUtils {

    public static class FeaturesHelper {

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

        public static FeaturesHelper create() {
            return new FeaturesHelper();
        }

        public static FeaturesHelper create(BundleContext bundleContext) {
            return create().bundleContext(bundleContext);
        }

        protected BundleContext bundleContext = FrameworkUtil.getBundle(FeaturesUtils.class).getBundleContext();

        protected String capabilityNamespace = null;

        protected boolean installedOnly = false;

        protected Bundle bundle = null;

        protected FeaturesHelper() {
            super();
        }

        public List<Feature> find() throws Exception {


            ServiceReference<FeaturesService> ref = bundleContext.getServiceReference(FeaturesService.class);
            FeaturesService featuresService = bundleContext.getService(ref);

            Feature[] featureArray =
                    isInstalledOnly() ? featuresService.listInstalledFeatures() : featuresService.listFeatures();

            List<Feature> features = Arrays.asList(featureArray);

            if (bundle != null) {

                ServiceReference<BundleService> ref0 = bundleContext.getServiceReference(BundleService.class);
                BundleService bundleService = bundleContext.getService(ref0);
                final String location = bundleService.getInfo(bundle).getUpdateLocation();
                bundleContext.ungetService(ref0);

                features = features.stream().filter(
                        f -> (f.getBundles().stream().filter(bi -> bi.getLocation().equals(location))
                                .count() > 0))
                        .collect(Collectors.toList());
            }

            if (CommonUtils.isValid(capabilityNamespace)) {
                features = features.stream()
                        .filter(f -> (new FeatureCapabilityHelper(f).isCapabilityProvided(capabilityNamespace)))
                        .collect(Collectors.toList());
            }

            bundleContext.ungetService(ref);

            return features;
        }

        public FeaturesUtils.FeaturesHelper bundleContext(BundleContext BundleContextValue) {
            this.setBundleContext(BundleContextValue);
            return this;
        }

        public FeaturesUtils.FeaturesHelper withCapabilityNamespace(String capabilityNamespaceValue) {
            this.setCapabilityNamespace(capabilityNamespaceValue);
            return this;
        };

        public FeaturesUtils.FeaturesHelper installedOnly() {
            this.setInstalledOnly(true);
            return this;
        };

        public FeaturesUtils.FeaturesHelper installedOnly(boolean InstalledOnlyValue) {
            this.setInstalledOnly(InstalledOnlyValue);
            return this;
        };

        public FeaturesUtils.FeaturesHelper containingBundle(Bundle bundleValue) {
            this.setBundle(bundleValue);
            return this;
        };

        public BundleContext getBundleContext() {
            return bundleContext;
        }

        public void setBundleContext(BundleContext bundleContext) {
            this.bundleContext = bundleContext;
        }

        public String getCapabilityNamespace() {
            return capabilityNamespace;
        }

        public void setCapabilityNamespace(String capabilityNamespace) {
            this.capabilityNamespace = capabilityNamespace;
        }

        public boolean isInstalledOnly() {
            return installedOnly;
        }

        public void setInstalledOnly(boolean installedOnly) {
            this.installedOnly = installedOnly;
        }

        public Bundle getBundle() {
            return bundle;
        }

        public void setBundle(Bundle bundle) {
            this.bundle = bundle;
        };

    }

}
