/*
 * 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.felix.utils.repository;

import java.io.InputStream;
import java.io.Writer;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.stream.Location;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import org.apache.felix.utils.resource.CapabilityImpl;
import org.apache.felix.utils.resource.RequirementImpl;
import org.apache.felix.utils.resource.ResourceImpl;
import org.apache.felix.utils.resource.SimpleFilter;
import org.apache.felix.utils.version.VersionTable;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
import org.osgi.service.repository.ContentNamespace;

import static javax.xml.stream.XMLStreamConstants.CHARACTERS;
import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;

/**
 * Repository XML xml based on StaX
 */
public final class StaxParser {

    public static final String REPOSITORY = "repository";
    public static final String REPO_NAME = "name";
    public static final String INCREMENT = "increment";
    public static final String REFERRAL = "referral";
    public static final String DEPTH = "depth";
    public static final String URL = "url";
    public static final String RESOURCE = "resource";
    public static final String CAPABILITY = "capability";
    public static final String REQUIREMENT = "requirement";
    public static final String NAMESPACE = "namespace";
    public static final String ATTRIBUTE = "attribute";
    public static final String DIRECTIVE = "directive";
    public static final String NAME = "name";
    public static final String VALUE = "value";
    public static final String TYPE = "type";

    public static final String REPOSITORY_NAMESPACE = "http://www.osgi.org/xmlns/repository/v1.0.0";

    static XMLInputFactory inputFactory;
    static XMLOutputFactory outputFactory;

    private StaxParser() {
    }

    public static class Referral {
        public String url;
        public int depth = Integer.MAX_VALUE;
    }

    public static class XmlRepository {
        public String name;
        public long increment;
        public List<Referral> referrals = new ArrayList<>();
        public List<Resource> resources = new ArrayList<>();
    }

    public static void write(XmlRepository repository, Writer os) throws XMLStreamException {
        XMLStreamWriter writer = getOutputFactory().createXMLStreamWriter(os);
        try {
            writer.writeStartDocument();
            writer.setDefaultNamespace(REPOSITORY_NAMESPACE);
            // repository element
            writer.writeStartElement(REPOSITORY_NAMESPACE, REPOSITORY);
            writer.writeAttribute("xmlns", REPOSITORY_NAMESPACE);
            writer.writeAttribute(REPO_NAME, repository.name);
            writer.writeAttribute(INCREMENT, Long.toString(repository.increment));
            // referrals
            for (Referral referral : repository.referrals) {
                writer.writeStartElement(REPOSITORY_NAMESPACE, REFERRAL);
                writer.writeAttribute(DEPTH, Integer.toString(referral.depth));
                writer.writeAttribute(URL, referral.url);
                writer.writeEndElement();
            }
            // resources
            for (Resource resource : repository.resources) {
                writer.writeStartElement(REPOSITORY_NAMESPACE, RESOURCE);
                for (Capability cap : resource.getCapabilities(null)) {
                    writeClause(writer, CAPABILITY, cap.getNamespace(), cap.getDirectives(), cap.getAttributes());
                }
                for (Requirement req : resource.getRequirements(null)) {
                    writeClause(writer, REQUIREMENT, req.getNamespace(), req.getDirectives(), req.getAttributes());
                }
                writer.writeEndElement();
            }
            writer.writeEndDocument();
            writer.flush();
        } finally {
            writer.close();
        }
    }

    private static void writeClause(XMLStreamWriter writer, String element, String namespace, Map<String, String> directives, Map<String, Object> attributes) throws XMLStreamException {
        writer.writeStartElement(REPOSITORY_NAMESPACE, element);
        writer.writeAttribute(NAMESPACE, namespace);
        for (Map.Entry<String, String> dir : directives.entrySet()) {
            writer.writeStartElement(REPOSITORY_NAMESPACE, DIRECTIVE);
            writer.writeAttribute(NAME, dir.getKey());
            writer.writeAttribute(VALUE, dir.getValue());
            writer.writeEndElement();
        }
        for (Map.Entry<String, Object> att : attributes.entrySet()) {
            String key = att.getKey();
            Object val = att.getValue();
            writer.writeStartElement(REPOSITORY_NAMESPACE, ATTRIBUTE);
            writer.writeAttribute(NAME, key);
            if (val instanceof Version) {
                writer.writeAttribute(TYPE, "Version");
            } else if (val instanceof Long) {
                writer.writeAttribute(TYPE, "Long");
            } else if (val instanceof Double) {
                writer.writeAttribute(TYPE, "Double");
            } else if (val instanceof Iterable) {
                Iterable<?> it = (Iterable<?>) att.getValue();
                String scalar = null;
                for (Object o : it) {
                    String ts;
                    if (o instanceof String) {
                        ts = "String";
                    } else if (o instanceof Long) {
                        ts = "Long";
                    } else if (o instanceof Double) {
                        ts = "Double";
                    } else if (o instanceof Version) {
                        ts = "Version";
                    } else {
                        throw new IllegalArgumentException("Unsupported scalar type: " + o);
                    }
                    if (scalar == null) {
                        scalar = ts;
                    } else if (!scalar.equals(ts)) {
                        throw new IllegalArgumentException("Unconsistent list type for attribute " + key);
                    }
                }
                writer.writeAttribute(TYPE, "List<" + scalar + ">");
                StringBuilder sb = new StringBuilder();
                boolean first = true;
                for (Object o : it) {
                    if (first) {
                        first = false;
                    } else {
                        sb.append(",");
                    }
                    sb.append(o.toString().replace(",", "\\,"));
                }
                val = sb.toString();
            }
            writer.writeAttribute(VALUE, val.toString());
            writer.writeEndElement();
        }
        writer.writeEndElement();
    }

    public static XmlRepository parse(InputStream is) throws XMLStreamException {
        return parse(null, is, null);
    }

    public static XmlRepository parse(URI repositoryUrl, InputStream is) throws XMLStreamException {
        return parse(repositoryUrl, is, null);
    }

    public static XmlRepository parse(URI repositoryUrl, InputStream is, XmlRepository previous) throws XMLStreamException {
        XMLStreamReader reader = getInputFactory().createXMLStreamReader(is);
        try {
            int event = reader.nextTag();
            if (event != START_ELEMENT || !REPOSITORY.equals(reader.getLocalName())) {
                throw new IllegalStateException("Expected element 'repository' at the root of the document");
            }
            XmlRepository repo = new XmlRepository();
            for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++) {
                String attrName = reader.getAttributeLocalName(i);
                String attrValue = reader.getAttributeValue(i);
                switch (attrName) {
                case REPO_NAME:
                    repo.name = attrValue;
                    break;
                case INCREMENT:
                    repo.increment = Long.parseLong(attrValue);
                    break;
                default:
                    throw new IllegalStateException("Unexpected attribute '" + attrName + "'");
                }
            }
            if (previous != null && repo.increment == previous.increment) {
                return previous;
            }
            while ((event = reader.nextTag()) == START_ELEMENT) {
                String element = reader.getLocalName();
                switch (element) {
                case REFERRAL:
                    Referral referral = new Referral();
                    for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++) {
                        String attrName = reader.getAttributeLocalName(i);
                        String attrValue = reader.getAttributeValue(i);
                        switch (attrName) {
                        case DEPTH:
                            referral.depth = Integer.parseInt(attrValue);
                            break;
                        case URL:
                            referral.url = attrValue;
                            break;
                        default:
                            throw new IllegalStateException("Unexpected attribute '" + attrName + "'");
                        }
                    }
                    if (referral.url == null) {
                        throw new IllegalStateException("Expected attribute '" + URL + "'");
                    }
                    repo.referrals.add(referral);
                    sanityCheckEndElement(reader, reader.nextTag(), REFERRAL);
                    break;
                case RESOURCE:
                    repo.resources.add(parseResource(repositoryUrl, reader));
                    break;
                default:
                    throw new IllegalStateException("Unsupported element '" + element + "'. Expected 'referral' or 'resource'");
                }
            }
            // Sanity check
            sanityCheckEndElement(reader, event, REPOSITORY);
            return repo;
        } finally {
            reader.close();
        }
    }

    private static void sanityCheckEndElement(XMLStreamReader reader, int event, String element) {
        if (event != END_ELEMENT || !element.equals(reader.getLocalName())) {
            throw new IllegalStateException("Unexpected state while finishing element " + element);
        }
    }

    private static ResourceImpl parseResource(URI repositoryUrl, XMLStreamReader reader) {
        try {
            if (reader.getAttributeCount() > 0) {
                throw new IllegalStateException("Unexpected attribute '" + reader.getAttributeLocalName(0) + "'");
            }
            ResourceImpl resource = new ResourceImpl();
            int event;
            while ((event = reader.nextTag()) == START_ELEMENT) {
                String element = reader.getLocalName();
                switch (element) {
                case CAPABILITY:
                    CapabilityImpl cap = parseCapability(reader, resource);
                    // Resolve relative resource urls now
                    if (repositoryUrl != null && ContentNamespace.CONTENT_NAMESPACE.equals(cap.getNamespace())) {
                        Object url = cap.getAttributes().get(ContentNamespace.CAPABILITY_URL_ATTRIBUTE);
                        if (url instanceof String) {
                            url = repositoryUrl.resolve(url.toString()).toString();
                            cap.getAttributes().put(ContentNamespace.CAPABILITY_URL_ATTRIBUTE, url);
                        }
                    }
                    resource.addCapability(cap);
                    break;
                case REQUIREMENT:
                    resource.addRequirement(parseRequirement(reader, resource));
                    break;
                default:
                    while ((event = reader.next()) != END_ELEMENT) {
                        switch (event) {
                        case START_ELEMENT:
                            throw new IllegalStateException("Unexpected element '" + reader.getLocalName() + "' inside 'resource' element");
                        case CHARACTERS:
                            throw new IllegalStateException("Unexpected text inside 'resource' element");
                        default:
                            break;
                        }
                    }
                    break;
                }
            }
            // Sanity check
            sanityCheckEndElement(reader, event, RESOURCE);
            return resource;
        } catch (Exception e) {
            Location loc = reader.getLocation();
            if (loc != null) {
                throw new IllegalStateException("Error while parsing resource at line " + loc.getLineNumber() + " and column " + loc.getColumnNumber(), e);
            } else {
                throw new IllegalStateException("Error while parsing resource", e);
            }
        }
    }

    private static CapabilityImpl parseCapability(XMLStreamReader reader, ResourceImpl resource) throws XMLStreamException {
        String[] namespace = new String[1];
        Map<String, String> directives = new HashMap<>();
        Map<String, Object> attributes = new HashMap<>();
        parseClause(reader, namespace, directives, attributes);
        sanityCheckEndElement(reader, reader.getEventType(), CAPABILITY);
        return new CapabilityImpl(resource, namespace[0], directives, attributes);
    }

    private static RequirementImpl parseRequirement(XMLStreamReader reader, ResourceImpl resource) throws XMLStreamException {
        String[] namespace = new String[1];
        Map<String, String> directives = new HashMap<>();
        Map<String, Object> attributes = new HashMap<>();
        parseClause(reader, namespace, directives, attributes);
        sanityCheckEndElement(reader, reader.getEventType(), REQUIREMENT);
        String filterStr = directives.get(Constants.FILTER_DIRECTIVE);
        SimpleFilter sf = (filterStr != null)
                ? SimpleFilter.parse(filterStr)
                : SimpleFilter.convert(attributes);
        return new RequirementImpl(resource, namespace[0], directives, attributes, sf);
    }

    private static void parseClause(XMLStreamReader reader, String[] namespace, Map<String, String> directives, Map<String, Object> attributes) throws XMLStreamException {
        namespace[0] = null;
        for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++) {
            String name = reader.getAttributeLocalName(i);
            String value = reader.getAttributeValue(i);
            if (NAMESPACE.equals(name)) {
                namespace[0] = value;
            } else {
                throw new IllegalStateException("Unexpected attribute: '" + name + "'. Expected 'namespace'");
            }
        }
        if (namespace[0] == null) {
            throw new IllegalStateException("Expected attribute 'namespace'");
        }
        while (reader.nextTag() == START_ELEMENT) {
            String element = reader.getLocalName();
            switch (element) {
            case DIRECTIVE: {
                String name = null;
                String value = null;
                for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++) {
                    String attName = reader.getAttributeLocalName(i);
                    String attValue = reader.getAttributeValue(i);
                    switch (attName) {
                    case NAME:
                        name = attValue;
                        break;
                    case VALUE:
                        value = attValue;
                        break;
                    default:
                        throw new IllegalStateException("Unexpected attribute: '" + attName + "'. Expected 'name', or 'value'.");
                    }
                }
                if (name == null || value == null) {
                    throw new IllegalStateException("Expected attribute 'name' and 'value'");
                }
                directives.put(name, value);
                sanityCheckEndElement(reader, reader.nextTag(), DIRECTIVE);
                break;
            }
            case ATTRIBUTE: {
                String name = null;
                String value = null;
                String type = "String";
                for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++) {
                    String attName = reader.getAttributeLocalName(i);
                    String attValue = reader.getAttributeValue(i);
                    switch (attName) {
                    case NAME:
                        name = attValue;
                        break;
                    case VALUE:
                        value = attValue;
                        break;
                    case TYPE:
                        type = attValue;
                        break;
                    default:
                        throw new IllegalStateException("Unexpected attribute: '" + attName + "'. Expected 'name', 'value' or 'type'.");
                    }
                }
                if (name == null || value == null) {
                    throw new IllegalStateException("Expected attribute 'name' and 'value'");
                }
                attributes.put(name, parseAttribute(value, type));
                sanityCheckEndElement(reader, reader.nextTag(), ATTRIBUTE);
                break;
            }
            default:
                throw new IllegalStateException("Unexpected element: '" + element + ". Expected 'directive' or 'attribute'");
            }
        }
    }

    private static Object parseAttribute(String value, String type) {
        if ("String".equals(type)) {
            return value;
        } else if ("Version".equals(type)) {
            return VersionTable.getVersion(value);
        } else if ("Long".equals(type)) {
            return Long.parseLong(value.trim());
        } else if ("Double".equals(type)) {
            return Double.parseDouble(value.trim());
        } else if (type.startsWith("List<") && type.endsWith(">")) {
            type = type.substring("List<".length(), type.length() - 1);
            List<Object> list = new ArrayList<>();
            for (String s : value.split(",")) {
                list.add(parseAttribute(s.trim(), type));
            }
            return list;
        } else {
            throw new IllegalStateException("Unexpected type: '" + type + "'");
        }
    }

    private static synchronized XMLInputFactory getInputFactory() {
        if (StaxParser.inputFactory == null) {
            XMLInputFactory factory = XMLInputFactory.newInstance();
            factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
            StaxParser.inputFactory = factory;
        }
        return StaxParser.inputFactory;
    }

    private static synchronized XMLOutputFactory getOutputFactory() {
        if (StaxParser.outputFactory == null) {
            StaxParser.outputFactory = XMLOutputFactory.newInstance();
        }
        return StaxParser.outputFactory;
    }

}