/*-
 * ~~~~~~licensing~~~~~~
 * system-commons
 * ==========
 * 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.esb.system.common.util;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.camel.Exchange;
import org.apache.xerces.dom.DocumentImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HeadersConverter {
    protected static final Logger log = LoggerFactory.getLogger(HeadersConverter.class);

    private String customHeaders;
    private String customHeaderPrefix;
    private String namespace;

    public void xml2camelHeaders(Exchange exchange) {
        NodeList nodes = exchange.getIn().getHeader(customHeaders, NodeList.class);

        if (nodes == null) {
            log.warn(customHeaders + " not found");
            return;
        }

        for (int i = 0; i < nodes.getLength(); ++i) {
            Node child = nodes.item(i).getFirstChild();
            String headerName = "";
            String headerValue = "";
            while (child != null) {
                if ("id".equals(child.getLocalName())) {
                    headerName = customHeaderPrefix + child.getTextContent();
                } else if ("value".equals(child.getLocalName())) {
                    headerValue = child.getTextContent();
                }
                child = child.getNextSibling();
            }
            if (!headerName.isEmpty()) {
                exchange.getIn().setHeader(headerName, headerValue);
            }
        }

        log.debug("Parsed xml custom headers count {}", nodes.getLength());
    }

    public void camelHeaders2xml(Exchange exchange) {
        Node item = null;
        Node child = null;
        Document xmlDoc = new DocumentImpl();
        Node list = xmlDoc.createElement("list");

        for (Map.Entry<String, Object> entry : exchange.getIn().getHeaders().entrySet()) {
            if (entry.getKey().startsWith(customHeaderPrefix)) {
                String name = entry.getKey().substring(customHeaderPrefix.length());
                if (entry.getValue() == null) break;
                String value = entry.getValue().toString();

                item = xmlDoc.createElementNS(namespace, "customHeader");

                child = xmlDoc.createElementNS(namespace, "id");
                child.appendChild(xmlDoc.createTextNode(name));
                item.appendChild(child);

                child = xmlDoc.createElementNS(namespace, "value");
                child.appendChild(xmlDoc.createTextNode(value));
                item.appendChild(child);

                list.appendChild(item);
            }
        }

        exchange.getIn().setHeader(customHeaders, list);
    }

    public void xml2Json(Exchange exchange) {
        NodeList nodes = exchange.getIn().getHeader(customHeaders, NodeList.class);

        if (nodes == null) {
            log.warn(customHeaders + " not found");
            return;
        }

        List<CustomHeader> customHeaders = new ArrayList<>();
        for (int i = 0; i < nodes.getLength(); ++i) {
            Node child = nodes.item(i).getFirstChild();
            String headerName = "";
            String headerValue = "";
            String headerType = "";
            while (child != null) {
                if ("id".equals(child.getLocalName())) {
                    headerName = child.getTextContent();
                } else if ("value".equals(child.getLocalName())) {
                    headerValue = child.getTextContent();
                } else if ("type".equals(child.getLocalName())) {
                    headerType = child.getTextContent();
                }
                child = child.getNextSibling();
            }
            if (!headerName.isEmpty()) {
                customHeaders.add(new CustomHeader(headerName, headerType, headerValue));
            }
        }
        Gson gson = new Gson();
        exchange.getIn().setHeader(this.customHeaders, gson.toJson(customHeaders));

        log.debug("Parsed xml custom headers count {}", nodes.getLength());
    }

    public void json2xml(Exchange exchange) {
        String headers = exchange.getIn().getHeader(customHeaders, String.class);

        if (headers == null) {
            log.warn(customHeaders + " not found");
            return;
        }

        Gson gson = new Gson();
        List<CustomHeader> customHeaders = gson.fromJson(headers, new TypeToken<ArrayList<CustomHeader>>() {
        }.getType());

        Node item = null;
        Node child = null;
        Document xmlDoc = new DocumentImpl();
        Node list = xmlDoc.createElement("list");

        for (CustomHeader customHeader : customHeaders) {
            item = xmlDoc.createElementNS(namespace, "customHeader");

            child = xmlDoc.createElementNS(namespace, "id");
            child.appendChild(xmlDoc.createTextNode(customHeader.getId()));
            item.appendChild(child);

            child = xmlDoc.createElementNS(namespace, "type");
            child.appendChild(xmlDoc.createTextNode(customHeader.getType()));
            item.appendChild(child);

            child = xmlDoc.createElementNS(namespace, "value");
            child.appendChild(xmlDoc.createTextNode(customHeader.getValue()));
            item.appendChild(child);

            list.appendChild(item);
        }

        exchange.getIn().setHeader(this.customHeaders, list);
    }

    public void setCustomHeaderPrefix(String customHeaderPrefix) {
        this.customHeaderPrefix = customHeaderPrefix;
    }

    public void setCustomHeaders(String customHeaders) {
        this.customHeaders = customHeaders;
    }

    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }
}
