/*-
 * ~~~~~~licensing~~~~~~
 * secure-vault-runtime
 * ==========
 * 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.runtime.resourcevault.internal;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map.Entry;

import org.apache.felix.utils.properties.Properties;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.entaxy.esb.platform.runtime.core.initializer.api.AbstractStandaloneInitializer;
import ru.entaxy.esb.platform.runtime.core.initializer.api.Initialized;
import ru.entaxy.esb.platform.runtime.core.initializer.api.StandaloneInitializer;
import ru.entaxy.esb.resources.EntaxyResourceService;
import ru.entaxy.platform.core.artifact.Artifact;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
import ru.entaxy.platform.core.artifact.Artifacts;
import ru.entaxy.platform.core.artifact.DeployedArtifact;
import ru.entaxy.platform.core.artifact.installer.builder.InstallationResult;
import ru.entaxy.platform.core.artifact.installer.builder.Installer;
import ru.entaxy.platform.core.artifact.installer.builder.typed.CommonBundleInstaller;
import ru.entaxy.platform.core.artifact.repository.impl.DeployedArtifactImpl;
import ru.entaxy.platform.core.artifact.service.ArtifactService;

@Deprecated(since = "1.10", forRemoval = true)
@StandaloneInitializer(id = "vault")
// @Component(service = VaultInitializer.class, immediate = true)
public class VaultInitializer extends AbstractStandaloneInitializer {

    private static final Logger log = LoggerFactory.getLogger(VaultInitializer.class);

    private final static int REPEAT_COUNT = 5;
    private final static int INTERVAL = 15000;

    public static final String PATH_SUFFIX = "init/install/vault.properties";

    @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC,
            policyOption = ReferencePolicyOption.GREEDY, target = "(id=artifacts)")
    volatile Initialized artifactsInitializerReady;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    ArtifactService artifactService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    EntaxyResourceService entaxyResourceService;

    @Activate
    public void activate(ComponentContext componentContext) {
        setBundleContext(componentContext.getBundleContext());

        Path configPath = Paths.get(System.getProperty("karaf.etc"), PATH_SUFFIX);
        File configFile = configPath.toFile();

        if (!configFile.exists())
            return;

        try {
            Properties properties = new Properties(configFile);

            for (Entry<String, String> entry : properties.entrySet()) {
                String url = entry.getKey();
                String paramsData = entry.getValue();
                InstallationParams params = InstallationParams.parse(paramsData);

                Artifact artifact = Artifacts.create(params.artifactCategory);

                artifact.getCoordinates().set(ArtifactCoordinates.fromUrl(url));

                DeployedArtifact depoyedArtifact = new DeployedArtifactImpl(artifact, "mvn:" + url);

                Installer<?> installer = params.installShared ? artifactService.installers().cluster()
                        : artifactService.installers().local();

                installer.artifact(depoyedArtifact);

                CommonBundleInstaller bundleInstaller = installer.typed(CommonBundleInstaller.class);

                InstallationResult result = null;
                for (int i = 0; i < REPEAT_COUNT; i++) {
                    result = bundleInstaller.installOnlyIfMissing().start().startLevel(params.startLevel).install();
                    if (result != null && result.isSuccessful())
                        break;
                    try {
                        Thread.sleep(INTERVAL);
                    } catch (InterruptedException e) {
                        log.trace(e.getMessage());
                    }
                }

                if (result.isSuccessful())
                    log.info("Installed successfully: [{}]", url);
                else {
                    log.error("Installation failed: [{}] :: {}", url, result.getMessage());
                    if (result.getError() != null) {
                        log.error("DETAILS:", result.getError());
                    }
                }
            }

        } catch (IOException e) {
            log.error("Error processing properties", e);
        }

    }

    protected static class InstallationParams {

        protected static final String SHARED_TARGET = "shared";

        public static InstallationParams parse(String data) {
            InstallationParams result = new InstallationParams();

            String[] values = data.split(";");
            result.installShared = values[0].equals(SHARED_TARGET);

            if (values.length > 1)
                result.artifactCategory = values[1].trim();

            if (values.length > 2)
                try {
                    result.startLevel = Integer.parseInt(values[2].trim());
                } catch (Exception ignore) {

                }

            return result;
        }

        boolean installShared = true;

        String artifactCategory = "jar";

        int startLevel = 100;

    }

}
