package incheon.ags.mrb.style.utils;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * XML 파싱 유틸리티
 * DOM Element 조회 헬퍼 메서드 모음
 */
public class XmlUtils {

    /**
     * 첫 번째 자식 엘리먼트 가져오기 (네임스페이스 무관)
     */
    public static Element getFirstElementByTagName(Node parent, String tagName) {
        if (parent instanceof Document) {
            NodeList nodeList = ((Document) parent).getElementsByTagNameNS("*", tagName);
            return nodeList.getLength() > 0 ? (Element) nodeList.item(0) : null;
        } else if (parent instanceof Element) {
            NodeList nodeList = ((Element) parent).getElementsByTagNameNS("*", tagName);
            return nodeList.getLength() > 0 ? (Element) nodeList.item(0) : null;
        }
        return null;
    }

    /**
     * 직계 자식 엘리먼트만 가져오기 (네임스페이스 무관)
     * 하위 요소는 검색하지 않고 바로 아래 자식만 검색
     */
    public static Element getDirectChildElementByTagName(Element parent, String tagName) {
        if (parent == null) {
            return null;
        }

        NodeList children = parent.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node child = children.item(i);
            if (child.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) child;
                String localName = element.getLocalName();
                if (localName != null && localName.equals(tagName)) {
                    return element;
                }
            }
        }
        return null;
    }

    /**
     * SLD XML에서 Symbolizer 타입을 읽어 layerType 자동 감지
     */
    public static String detectLayerTypeFromSld(Document doc) {
        Element userStyleElement = getFirstElementByTagName(doc, "UserStyle");
        if (userStyleElement != null) {
            Element featureTypeStyleElement = getFirstElementByTagName(userStyleElement, "FeatureTypeStyle");
            if (featureTypeStyleElement != null) {
                Element rule = getFirstElementByTagName(featureTypeStyleElement, "Rule");
                if (rule != null) {
                    // LineSymbolizer 확인
                    if (getFirstElementByTagName(rule, "LineSymbolizer") != null) {
                        return "line";
                    }
                    // PolygonSymbolizer 확인
                    if (getFirstElementByTagName(rule, "PolygonSymbolizer") != null) {
                        return "polygon";
                    }
                    // PointSymbolizer 확인
                    if (getFirstElementByTagName(rule, "PointSymbolizer") != null) {
                        return "point";
                    }
                }
            }
        }
        // 기본값
        return "point";
    }

    /**
     * XML 전처리: BOM 제거 및 공백 정리
     */
    public static String preprocessXml(String xml) {
        if (xml == null) {
            return null;
        }

        // BOM(Byte Order Mark) 제거
        String cleaned = xml;
        if (cleaned.startsWith("\uFEFF")) {
            cleaned = cleaned.substring(1);
        }

        // 앞뒤 공백 제거
        cleaned = cleaned.trim();

        // 잘못된 제어 문자 제거 (프롤로그 오류를 야기할 수 있는 문자들)
        cleaned = cleaned.replaceAll("[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]", "");

        // XML 선언 앞의 불필요한 공백이나 문자 제거
        if (cleaned.contains("<?xml")) {
            int xmlDeclIndex = cleaned.indexOf("<?xml");
            if (xmlDeclIndex > 0) {
                // XML 선언 앞에 불필요한 문자가 있으면 제거
                cleaned = cleaned.substring(xmlDeclIndex);
            }
        }

        return cleaned;
    }
}
