/*
 * Copyright (C) 2016 Reece H. Dunn
 *
 * Licensed 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 uk.co.reecedunn.intellij.plugin.xquery.lang;

import org.jetbrains.annotations.NotNull;
import org.w3c.dom.*;
import uk.co.reecedunn.intellij.plugin.xquery.resources.XQueryBundle;

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

public class ImplementationItem {
    public static final String IMPLEMENTATION_VERSION = "version";
    public static final String IMPLEMENTATION_DIALECT = "dialect";
    public static final String STATIC_CONTEXT = "static-context";

    public static final ImplementationItem NULL_ITEM = new ImplementationItem();

    private final Element mElement;
    private final String mID;
    private final String mName;

    private ImplementationItem() {
        mElement = null;
        mID = null;
        mName = XQueryBundle.message("xquery.implementation.not-supported");
    }

    ImplementationItem(Document document) {
        mElement = document.getDocumentElement();
        mID = null;
        mName = null;
    }

    private ImplementationItem(Element element) {
        final NamedNodeMap attributes = element.getAttributes();
        mElement = element;
        mID = attributes.getNamedItem("id").getNodeValue();
        if (attributes.getNamedItem("localized").getNodeValue().equals("true")) {
            mName = XQueryBundle.message(attributes.getNamedItem("name").getNodeValue());
        } else {
            mName = attributes.getNamedItem("name").getNodeValue();
        }
    }

    public String getID() {
        return mID;
    }

    public String toString() {
        return mName;
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof ImplementationItem))
            return false;
        ImplementationItem otherItem = (ImplementationItem)other;
        if (otherItem.getID() == null) {
            return mID == null;
        }
        return otherItem.getID().equals(mID);
    }

    public List<ImplementationItem> getItems(String tagName) {
        final List<ImplementationItem> items = new ArrayList<>();
        if (mElement != null) {
            NodeList nodes = mElement.getElementsByTagName(tagName);
            for (int i = 0; i != nodes.getLength(); ++i) {
                items.add(new ImplementationItem((Element)nodes.item(i)));
            }
        }
        if (items.isEmpty()) {
            items.add(ImplementationItem.NULL_ITEM);
        }
        return items;
    }

    public ImplementationItem getDefaultItem(String tagName) {
        if (mElement != null) {
            NodeList nodes = mElement.getElementsByTagName(tagName);
            for (int i = 0; i != nodes.getLength(); ++i) {
                Node node = nodes.item(i);
                if (node.getAttributes().getNamedItem("default").getNodeValue().equals("true")) {
                    return new ImplementationItem((Element)node);
                }
            }
        }
        return NULL_ITEM;
    }

    @NotNull
    private XQueryVersion getVersion(Versioned featureName) {
        if (mElement != null) {
            NodeList nodes = mElement.getElementsByTagName(featureName.getId());
            if (nodes.getLength() != 0) {
                Node node = nodes.item(0);
                return XQueryVersion.parse(node.getAttributes().getNamedItem("version").getNodeValue());
            }
        }
        return XQueryVersion.UNSUPPORTED;
    }

    public List<ImplementationItem> getItemsByVersion(String tagName, Versioned featureName, Specification version) {
        final List<ImplementationItem> items = new ArrayList<>();
        if (mElement != null) {
            NodeList nodes = mElement.getElementsByTagName(tagName);
            for (int i = 0; i != nodes.getLength(); ++i) {
                ImplementationItem item = new ImplementationItem((Element)nodes.item(i));
                if (version.getLabel().equals(item.getVersion(featureName).toString())) {
                    items.add(item);
                }
            }
        }
        if (items.isEmpty()) {
            items.add(ImplementationItem.NULL_ITEM);
        }
        return items;
    }

    public ImplementationItem getDefaultItemByVersion(String tagName, Versioned featureName, Specification version) {
        if (mElement != null) {
            NodeList nodes = mElement.getElementsByTagName(tagName);
            for (int i = 0; i != nodes.getLength(); ++i) {
                Node node = nodes.item(i);
                if (node.getAttributes().getNamedItem("default").getNodeValue().equals("true")) {
                    ImplementationItem item = new ImplementationItem((Element)nodes.item(i));
                    if (version.getLabel().equals(item.getVersion(featureName).toString())) {
                        return item;
                    }
                }
            }
        }
        return NULL_ITEM;
    }

    public String getSpecification(Versioned featureName) {
        if (mElement != null) {
            NodeList nodes = mElement.getElementsByTagName(featureName.getId());
            if (nodes.getLength() != 0) {
                Node node = nodes.item(0);
                return node.getAttributes().getNamedItem("specification").getNodeValue();
            }
        }
        return null;
    }

    public ImplementationItem getItemById(String id) {
        if (mElement != null) {
            return getItemById(mElement, id);
        }
        return NULL_ITEM;
    }

    private ImplementationItem getItemById(Element element, String id) {
        NodeList nodes = element.getChildNodes();
        for (int i = 0; i != nodes.getLength(); ++i) {
            Node node = nodes.item(i);
            if (node.getNodeType() != Node.ELEMENT_NODE) continue;

            Node attributeId = node.getAttributes().getNamedItem("id");
            if (attributeId != null && attributeId.getNodeValue().equals(id)) {
                return new ImplementationItem((Element)node);
            }

            ImplementationItem item = getItemById((Element)node, id);
            if (item != NULL_ITEM) {
                return item;
            }
        }
        return NULL_ITEM;
    }

    public String getStaticContext() {
        NodeList nodes = mElement.getElementsByTagName(STATIC_CONTEXT);
        for (int i = 0; i != nodes.getLength(); ++i) {
            Element e = (Element)nodes.item(i);
            return e.getAttribute("uri");
        }
        return null;
    }
}

@@ -648,50 +648,8 @@
 g;%0A%0A
-import org.jetbrains.annotations.NotNull;%0A
 impo
@@ -3464,42 +3464,22 @@
     
-@NotNull%0A    private XQueryVersion
+private String
  get
@@ -3736,28 +3736,8 @@
 urn 
-XQueryVersion.parse(
 node
@@ -3783,33 +3783,32 @@
 ).getNodeValue()
-)
 ;%0A            %7D%0A
@@ -3836,33 +3836,12 @@
 urn 
-XQueryVersion.UNSUPPORTED
+null
 ;%0A  
@@ -4349,35 +4349,24 @@
 featureName)
-.toString()
 )) %7B%0A       
@@ -5155,19 +5155,8 @@
 ame)
-.toString()
 )) %7B

Make ImplementationItem.getVersion return a string.