/*
 * 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.w3c.dom.*;
import org.xml.sax.InputSource;
import uk.co.reecedunn.intellij.plugin.xquery.XQueryBundle;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class Implementations {
    public static class Item {
        private final String mID;
        private final String mName;

        Item() {
            mID = null;
            mName = null;
        }

        Item(Element element) {
            final NamedNodeMap attributes = element.getAttributes();
            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 Item))
                return false;
            return ((Item)other).getID().equals(mID);
        }
    }

    private static final Item NULL_ITEM = new Item();
    private static final Element sImplementations = loadImplementations();

    private static Element loadImplementations() {
        ClassLoader loader = Implementations.class.getClassLoader();
        InputStream input = loader.getResourceAsStream("data/implementations.xml");
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            return builder.parse(new InputSource(input)).getDocumentElement();
        } catch (Exception e) {
            return null;
        }
    }

    public static List<Item> getImplementations() {
        final List<Item> items = new ArrayList<>();
        if (sImplementations != null) {
            NodeList nodes = sImplementations.getElementsByTagName("implementation");
            for (int i = 0; i != nodes.getLength(); ++i) {
                items.add(new Item((Element)nodes.item(i)));
            }
        }
        return items;
    }

    public static Item getDefaultImplementation() {
        if (sImplementations != null) {
            NodeList nodes = sImplementations.getElementsByTagName("implementation");
            for (int i = 0; i != nodes.getLength(); ++i) {
                Node node = nodes.item(i);
                if (node.getAttributes().getNamedItem("default").getNodeValue().equals("true")) {
                    return new Item((Element)node);
                }
            }
        }
        return NULL_ITEM;
    }
}

@@ -2595,37 +2595,38 @@
   %7D%0A    %7D%0A%0A    p
-ublic
+rivate
  static List%3CIte
@@ -2632,31 +2632,61 @@
 em%3E getI
-mplementations(
+temsByTagName(Element element, String tagName
 ) %7B%0A    
@@ -2745,32 +2745,23 @@
     if (
-sImp
+e
 lement
-ations
  != null
@@ -2793,32 +2793,23 @@
 nodes = 
-sImp
+e
 lement
-ations
 .getElem
@@ -2822,32 +2822,23 @@
 TagName(
-%22implementation%22
+tagName
 );%0A     
@@ -3006,29 +3006,30 @@
     %7D%0A%0A    p
-ublic
+rivate
  static Item
@@ -3044,22 +3044,52 @@
 ultI
-mplementation(
+temByTagName(Element element, String tagName
 ) %7B%0A
@@ -3100,32 +3100,23 @@
     if (
-sImp
+e
 lement
-ations
  != null
@@ -3148,32 +3148,23 @@
 nodes = 
-sImp
+e
 lement
-ations
 .getElem
@@ -3181,24 +3181,15 @@
 ame(
-%22implementation%22
+tagName
 );%0A 
@@ -3512,11 +3512,275 @@
 M;%0A    %7D
+%0A%0A    public static List%3CItem%3E getImplementations() %7B%0A        return getItemsByTagName(sImplementations, %22implementation%22);%0A    %7D%0A%0A    public static Item getDefaultImplementation() %7B%0A        return getDefaultItemByTagName(sImplementations, %22implementation%22);%0A    %7D
 %0A%7D%0A

Create helper methods for navigating the implementations.xml hierarchy.