/*-
 * ~~~~~~licensing~~~~~~
 * application-impl
 * ==========
 * 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.integration.applications.impl.build;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.entaxy.esb.resources.EntaxyResource;
import ru.entaxy.platform.core.artifact.ArtifactCoordinates;
import ru.entaxy.platform.integration.applications.impl.ServiceHelper;
import ru.entaxy.platform.integration.applications.impl.jar.FolderBasedJarBuilder;

public class ResourceStorage extends AbstractStorage<ResourceDescriptor> {

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

    static final String startDirName = "resources/resources";

    static final String subDirName = "ru/entaxy/resource";

    static final String storageDirName = startDirName + "/" + subDirName;

    protected File startDir;

    public ResourceStorage(File parentDir, File tempDir) {
        super(parentDir, tempDir);
        this.startDir = new File(Paths.get(parentDir.getAbsolutePath(), startDirName).toAbsolutePath().toUri());

    }

    @Override
    protected String getStorageDir() {
        return storageDirName;
    }

    @Override
    public void prepare() {
        for (ResourceDescriptor descriptor : descriptors)
            prepareDescriptor(descriptor);

    }

    @Override
    public void prepareDescriptor(ResourceDescriptor descriptor) {
        EntaxyResource entaxyResource =
                ServiceHelper.getInstance().getEntaxyResourceService().getResource(descriptor.resourceUrl);
        if (!entaxyResource.exists()) {
            LOG.error("Resource doesn't exist: [{}]", descriptor.resourceUrl);
            return;
        }
        String targetPath = descriptor.resourceUrl.replace(':', '/');
        File targetFile = new File(Paths.get(rootDirectory.getAbsolutePath(), targetPath).toAbsolutePath().toUri());
        targetFile.getParentFile().mkdirs();

        try (InputStream is = entaxyResource.getInputStream();
                OutputStream os = new FileOutputStream(targetFile)) {

            os.write(is.readAllBytes());

            String targetLocation =
                    storageDirName.concat(targetFile.getAbsolutePath().replace(rootDirectory.getAbsolutePath(), ""))
                            .replace('\\', '/');

            descriptor.finalLocation = targetLocation;


        } catch (Exception e) {
            LOG.error("Error reading resource [" + descriptor.resourceUrl + "]", e);
            return;
        }

    }

    @Override
    public BuildResult build(ArtifactCoordinates applicationCoordinates) {

        // first check if we have resources
        try (Stream<Path> pathStream = Files.walk(startDir.getAbsoluteFile().toPath())) {
            long count = pathStream
                    .parallel()
                    .filter(p -> !p.toFile().isDirectory())
                    .count();
            if (count == 0)
                return new BuildResult();
        } catch (IOException e) {
            LOG.error("ERROR checking the directory [" + startDir.getAbsolutePath() + "]", e);
            return new BuildResult();
        }

        ArtifactCoordinates jarCoordinates = ArtifactCoordinates.fromUrl(applicationCoordinates.toString());
        jarCoordinates.type("jar").classifier("resources");

        File jarFile = new File(Paths
                .get(tempDir.getAbsolutePath(), ".resources", jarCoordinates.getGroupId().replace('.', '/'),
                        jarCoordinates.getArtifactId(),
                        jarCoordinates.getVersion(),
                        jarCoordinates.getArtifactId().concat("-")
                                .concat(jarCoordinates.getVersion().concat("-")
                                        .concat(jarCoordinates.getClassifier().concat(".")
                                                .concat(jarCoordinates.getType()))))
                .toAbsolutePath().toUri());

        jarFile.getAbsoluteFile().getParentFile().mkdirs();

        String bundleName = String.format("APPLICATION :: %s :: %s :: RESOURCES", jarCoordinates.getArtifactId(),
                jarCoordinates.getVersion());
        String bundleDecription = bundleName;
        String bundleSymboliName =
                jarCoordinates.getGroupId().concat(".").concat(jarCoordinates.getArtifactId()).concat(".resources");

        FolderBasedJarBuilder jarBuilder = new FolderBasedJarBuilder(jarFile, startDir);
        jarBuilder.getOsgiInfo()
                .name(bundleName)
                .symbolicName(bundleSymboliName)
                .description(bundleDecription)
                .version(jarCoordinates.getVersion())
                .update();

        jarBuilder.putAttribute("Entaxy-Resource-Provider", "true");

        try {
            jarBuilder.loadFiles();
        } catch (IllegalStateException | IOException e) {
            LOG.error("Error loading files", e);
        }

        try {
            jarBuilder.close();
        } catch (IOException e) {
            LOG.error("Error closing jar", e);
        }

        BundleDescriptor bundleDesc = new BundleDescriptor();
        bundleDesc.id = -1;
        bundleDesc.symbolicName = bundleSymboliName;
        bundleDesc.mavenLocation = jarCoordinates.toString();
        bundleDesc.installLocation = "mvn:" + bundleDesc.mavenLocation;
        try {
            bundleDesc.sourceLocation = jarFile.getAbsoluteFile().toURI().toURL().toString();
        } catch (MalformedURLException e) {
            bundleDesc.sourceLocation = "file:///" + jarFile.getAbsolutePath().replace('\\', '/');
        }
        bundleDesc.priority = 90;

        BuildResult result = new BuildResult();
        result.newDescriptors.put(bundleSymboliName, bundleDesc);

        for (ResourceDescriptor desc : descriptors)
            result.changes.put(desc.resourceUrl, bundleDesc);


        return result;
    }
}
