/*-
 * ~~~~~~licensing~~~~~~
 * test-producers
 * ==========
 * 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.artifact;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.jar.Manifest;

import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class BlueprintManifest implements ArtifactManifest {

	private static final Logger log = LoggerFactory.getLogger(BlueprintManifest.class);
	
	protected Artifact artifact;
	
	protected Manifest manifest = new Manifest();
	
	boolean isLoaded = false;
	
	protected Map<String, String> customAttributes = new HashMap<>();
	
	public BlueprintManifest(Artifact artifact) {
		super();
		this.artifact = artifact;
	}
	
	public void load(Document document) {
		this.isLoaded = false;
		manifest = new Manifest();

		manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
		manifest.getMainAttributes().putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
		manifest.getMainAttributes().putValue(Constants.DYNAMICIMPORT_PACKAGE, "*");
        
		manifest.getMainAttributes().putValue(HEADERS.ENTAXY_BUNDLE, "true");
		manifest.getMainAttributes().putValue(HEADERS.ENTAXY_RUNTIME, "true");
		
		NodeList l = document.getElementsByTagName("manifest");
        if (l != null) {
            for (int i = 0; i < l.getLength(); i++) {
                Element e = (Element) l.item(i);
                String text = e.getTextContent();
                Properties props = new Properties();
                try {
					props.load(new ByteArrayInputStream(text.trim().getBytes()));
				} catch (IOException e1) {
					log.error("Error loading manifest", e1);
				}
                Enumeration en = props.propertyNames();
                while (en.hasMoreElements()) {
                    String k = (String) en.nextElement();
                    String v = props.getProperty(k);
                    manifest.getMainAttributes().putValue(k, v);
                }
                e.getParentNode().removeChild(e);
            }
        }
        this.isLoaded = true;
	}
	
	protected void appendCustoms(Document document) {
		for (Entry<String, String> entry: this.customAttributes.entrySet())
			this.manifest.getMainAttributes().putValue(entry.getKey(), entry.getValue());
	}
	
	protected void beforeSave(Document document) {
	    this.manifest.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME
	    		, this.artifact.getCoordinates().getGroupId() + "." + this.artifact.getCoordinates().getArtifactId());
	    this.manifest.getMainAttributes().putValue(Constants.BUNDLE_NAME
	    		, this.artifact.getCoordinates().getGroupId() + "." + this.artifact.getCoordinates().getArtifactId());
	    this.manifest.getMainAttributes().putValue(Constants.BUNDLE_VERSION
	    		, this.artifact.getCoordinates().getVersion().replaceAll("-", "."));
	    appendCustoms(document);
	}
	
	public void save(Document document) {
		beforeSave(document);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        String manifestContent = "";
        try {
        	this.manifest.write(bos);
			manifestContent = bos.toString(StandardCharsets.UTF_8);
			manifestContent = manifestContent.replaceAll("\r", "").replaceAll("\n ", "");
		} catch (IOException e) {
			log.error("Error saving manifest to document", e);
		}
        
        // remove old manifests
		NodeList l = document.getElementsByTagName("manifest");
        if (l != null)
            for (int i = 0; i < l.getLength(); i++) {
            	Element e = (Element) l.item(i);
            	e.getParentNode().removeChild(e);
            }

        
        Element manifest = document.createElementNS("http://karaf.apache.org/xmlns/deployer/blueprint/v1.0.0", "manifest");
        manifest.setTextContent(manifestContent);
        document.getDocumentElement().insertBefore(manifest
        		, document.getDocumentElement().getFirstChild());
		
	}
	
	@Override
	public Map<String, String> getCustomAttributes() {
		return this.customAttributes;
	}

	public boolean isLoaded() {
		return isLoaded;
	}
	
}
