/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.bval.jsr.xml;

import java.net.URL;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;

import jakarta.validation.ValidationException;
import javax.xml.XMLConstants;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.UnmarshallerHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.ValidatorHandler;

import org.apache.bval.util.Exceptions;
import org.apache.bval.util.Lazy;
import org.apache.bval.util.StringUtils;
import org.apache.bval.util.Validate;
import org.apache.bval.util.reflection.Reflection;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.XMLFilterImpl;

/**
 * Unmarshals XML converging on latest schema version. Presumes backward compatiblity between schemae.
 */
public class SchemaManager {
    public static class Builder {
        private final Map<Key, Lazy<Schema>> data = new LinkedHashMap<>();

        public Builder add(String version, String ns, String resource) {
            data.put(new Key(version, ns), new Lazy<>(() -> SchemaManager.loadSchema(resource)));
            return this;
        }

        public SchemaManager build() {
            return new SchemaManager(data);
        }
    }

    private static class Key implements Comparable<Key> {
        private static final Comparator<Key> CMP = Comparator.comparing(Key::getVersion).thenComparing(Key::getNs);

        final String version;
        final String ns;

        Key(String version, String ns) {
            super();
            Validate.isTrue(StringUtils.isNotBlank(version), "version cannot be null/empty/blank");
            this.version = version;
            Validate.isTrue(StringUtils.isNotBlank(ns), "ns cannot be null/empty/blank");
            this.ns = ns;
        }

        public String getVersion() {
            return version;
        }

        public String getNs() {
            return ns;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == this) {
                return true;
            }
            return Optional.ofNullable(obj).filter(SchemaManager.Key.class::isInstance)
                .map(SchemaManager.Key.class::cast)
                .filter(k -> Objects.equals(this.version, k.version) && Objects.equals(this.ns, k.ns)).isPresent();
        }

        @Override
        public int hashCode() {
            return Objects.hash(version, ns);
        }

        @Override
        public String toString() {
            return String.format("%s:%s", version, ns);
        }

        @Override
        public int compareTo(Key o) {
            return CMP.compare(this, o);
        }
    }

    private class DynamicValidatorHandler extends XMLFilterImpl {
        ContentHandler ch;
        SAXParseException e;

        @Override
        public void setContentHandler(ContentHandler handler) {
            super.setContentHandler(handler);
            this.ch = handler;
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
            if (getContentHandler() == ch) {
                final String version = Objects.toString(atts.getValue("version"), data.keySet().iterator().next().getVersion());
                final Key schemaKey = new Key(version, uri);
                Exceptions.raiseUnless(data.containsKey(schemaKey), ValidationException::new,
                    "Unknown validation schema %s", schemaKey);

                final Schema schema = data.get(schemaKey).get();
                final ValidatorHandler vh = schema.newValidatorHandler();
                vh.startDocument();
                vh.setContentHandler(ch);
                super.setContentHandler(vh);
            }
            try {
                super.startElement(uri, localName, qName, atts);
            } catch (SAXParseException e) {
                this.e = e;
            }
        }

        @Override
        public void error(SAXParseException e) throws SAXException {
            this.e = e;
            super.error(e);
        }

        @Override
        public void fatalError(SAXParseException e) throws SAXException {
            this.e = e;
            super.fatalError(e);
        }

        void validate() throws SAXParseException {
            if (e != null) {
                throw e;
            }
        }
    }

    //@formatter:off
    private enum XmlAttributeType {
        CDATA, ID, IDREF, IDREFS, NMTOKEN, NMTOKENS, ENTITY, ENTITIES, NOTATION;
        //@formatter:on
    }

    private class SchemaRewriter extends XMLFilterImpl {

        private boolean root = true;
        private Key rootSchemaKey = null;

        @Override
        public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {

            // if no version attribute is available, we pick up the first known version (aka 1.1 most likely)
            // not sure if that is either possible and correct
            if (root) {
                rootSchemaKey = new Key(
                    Objects.toString(atts.getValue("version"), data.keySet().iterator().next().getVersion()),
                    uri);
            }

            // no matter what we see now, if the namespace from the root element is different, we override the namespace
            // the root version attribute gets also overridden for the root element only
            if (!target.equals(rootSchemaKey)) {
                uri = target.ns;
                if (root) {
                    atts = rewriteVersion(atts);
                    root = false;
                }
            }

            super.startElement(uri, localName, qName, atts);
        }

        private Attributes rewriteVersion(Attributes atts) {
            final AttributesImpl result;
            if (atts instanceof AttributesImpl) {
                result = (AttributesImpl) atts;
            } else {
                result = new AttributesImpl(atts);
            }
            set(result, "", VERSION_ATTRIBUTE, "", XmlAttributeType.CDATA, target.version);
            return result;
        }

        private void set(AttributesImpl attrs, String uri, String localName, String qName, XmlAttributeType type,
            String value) {
            for (int i = 0, sz = attrs.getLength(); i < sz; i++) {
                if (Objects.equals(qName, attrs.getQName(i))
                    || Objects.equals(uri, attrs.getURI(i)) && Objects.equals(localName, attrs.getLocalName(i))) {
                    attrs.setAttribute(i, uri, localName, qName, type.name(), value);
                    return;
                }
            }
            attrs.addAttribute(uri, localName, qName, type.name(), value);
        }
    }

    public static final String VERSION_ATTRIBUTE = "version";

    private static final Logger log = Logger.getLogger(SchemaManager.class.getName());
    private static final SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    private static final SAXParserFactory SAX_PARSER_FACTORY;

    static {
        SAX_PARSER_FACTORY = SAXParserFactory.newInstance();
        SAX_PARSER_FACTORY.setNamespaceAware(true);
    }

    static Schema loadSchema(String resource) {
        final URL schemaUrl = Reflection.loaderFromClassOrThread(SchemaManager.class).getResource(resource);
        try {
            return SCHEMA_FACTORY.newSchema(schemaUrl);
        } catch (SAXException e) {
            log.log(Level.WARNING, String.format("Unable to parse schema: %s", resource), e);
            return null;
        }
    }

    private static Class<?> getObjectFactory(Class<?> type) throws ClassNotFoundException {
        final String className = String.format("%s.%s", type.getPackage().getName(), "ObjectFactory");
        return Reflection.toClass(className, type.getClassLoader());
    }

    private final Key target;
    private final Map<Key, Lazy<Schema>> data;
    private final String description;

    private SchemaManager(Map<Key, Lazy<Schema>> data) {
        super();
        this.data = Collections.unmodifiableMap(data);
        this.target = data.keySet().stream().skip(data.size() - 1).findFirst().orElseThrow(IllegalStateException::new);
        this.description = target.ns.substring(target.ns.lastIndexOf('/') + 1);
    }

    public Optional<Schema> getSchema(String ns, String version) {
        return Optional.of(new Key(version, ns)).map(data::get).map(Lazy::get);
    }

    public Optional<Schema> getSchema(Document document) {
        return Optional.ofNullable(document).map(Document::getDocumentElement)
            .map(e -> getSchema(e.getAttribute(XMLConstants.XMLNS_ATTRIBUTE), e.getAttribute(VERSION_ATTRIBUTE))).get();
    }

    public <E extends Exception> Schema requireSchema(Document document, Function<String, E> exc) throws E {
        return getSchema(document).orElseThrow(() -> Objects.requireNonNull(exc, "exc")
            .apply(String.format("Unknown %s schema", Objects.toString(description, ""))));
    }

    public <T> T unmarshal(InputSource input, Class<T> type) throws Exception {
        final XMLReader xmlReader = SAX_PARSER_FACTORY.newSAXParser().getXMLReader();

        // validate specified schema:
        final DynamicValidatorHandler schemaValidator = new DynamicValidatorHandler();
        xmlReader.setContentHandler(schemaValidator);

        // rewrite to latest schema, if required:
        final SchemaRewriter schemaRewriter = new SchemaRewriter();
        schemaValidator.setContentHandler(schemaRewriter);

        JAXBContext jc = JAXBContext.newInstance(getObjectFactory(type));
        // unmarshal:
        final UnmarshallerHandler unmarshallerHandler = jc.createUnmarshaller().getUnmarshallerHandler();
        schemaRewriter.setContentHandler(unmarshallerHandler);

        xmlReader.parse(input);
        schemaValidator.validate();

        @SuppressWarnings("unchecked")
        final JAXBElement<T> result = (JAXBElement<T>) unmarshallerHandler.getResult();
        return result.getValue();
    }
}
