/*
 * 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.psi.impl.xquery;

import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import uk.co.reecedunn.intellij.plugin.xquery.ast.xquery.XQueryModule;
import uk.co.reecedunn.intellij.plugin.xquery.ast.xquery.XQueryProlog;
import uk.co.reecedunn.intellij.plugin.core.functional.Option;
import uk.co.reecedunn.intellij.plugin.xquery.psi.XQueryNamespace;
import uk.co.reecedunn.intellij.plugin.xquery.psi.XQueryNamespaceResolver;
import uk.co.reecedunn.intellij.plugin.xquery.psi.XQueryPrologResolver;
import uk.co.reecedunn.intellij.plugin.xquery.psi.impl.TextPsiElementImpl;

import java.util.HashMap;
import java.util.Map;

import static uk.co.reecedunn.intellij.plugin.core.functional.PsiTreeWalker.children;

public class XQueryModulePsiImpl extends ASTWrapperPsiElement implements XQueryModule, XQueryNamespaceResolver, XQueryPrologResolver {
    private Map<String, TextPsiElementImpl> strings = new HashMap<>();

    public XQueryModulePsiImpl(@NotNull ASTNode node) {
        super(node);
    }

    @Nullable
    @Override
    public Option<XQueryNamespace> resolveNamespace(CharSequence prefix) {
        if (prefix != null && prefix.equals("local")) {
            PsiElement prefixElement = getStringElement("local");
            PsiElement uriElement = getStringElement("http://www.w3.org/2005/xquery-local-functions");
            return Option.some(new XQueryNamespace(prefixElement, uriElement, this));
        }
        return Option.none();
    }

    @Override
    public Option<XQueryProlog> resolveProlog() {
        return children(this).findFirst(XQueryProlog.class);
    }

    private PsiElement getStringElement(String string) {
        TextPsiElementImpl element = strings.getOrDefault(string, null);
        if (element == null) {
            element = new TextPsiElementImpl(getProject(), string);
            strings.put(string, element);
        }
        return element;
    }
}

@@ -742,16 +742,61 @@
 STNode;%0A
+import com.intellij.openapi.project.Project;%0A
 import c
@@ -1401,16 +1401,94 @@
 entImpl;
+%0Aimport uk.co.reecedunn.intellij.plugin.xquery.settings.XQueryProjectSettings;
 %0A%0Aimport
@@ -1780,53 +1780,142 @@
 ng, 
-TextPsiElementImpl%3E strings = new HashMap%3C%3E()
+XQueryNamespace%3E predefinedNamespaces = new HashMap%3C%3E();%0A    private XQueryProjectSettings settings;%0A    private String dialectId = %22%22
 ;%0A%0A 
@@ -1990,16 +1990,84 @@
 (node);%0A
+        settings = XQueryProjectSettings.getInstance(getProject());%0A
     %7D%0A%0A 
@@ -2180,320 +2180,117 @@
     
-if (prefix != null && prefix.equals(%22local%22)) %7B%0A            PsiElement prefixElement = getStringElement(%22local%22);%0A            PsiElement uriElement = getStringElement(%22http://www.w3.org/2005/xquery-local-functions%22);%0A            return Option.some(new XQueryNamespace(prefixElement, uriElement, this));%0A        %7D
+XQueryNamespace ns = getPredefinedNamespaces().getOrDefault(prefix != null ? prefix.toString() : null, null);
 %0A   
@@ -2312,13 +2312,13 @@
 ion.
-none(
+of(ns
 );%0A 
@@ -2471,170 +2471,586 @@
 ate 
-PsiElement getStringElement(String string) %7B%0A        TextPsiElementImpl element = strings.getOrDefault(string, null);%0A        if (element == null) %7B%0A            e
+Map%3CString, XQueryNamespace%3E getPredefinedNamespaces() %7B%0A        String id = settings.getDialectForXQueryVersion(settings.getXQueryVersion()).getID();%0A        if (!id.equals(dialectId)) %7B%0A            dialectId = id;%0A            predefinedNamespaces.clear();%0A%0A            Project project = getProject();%0A            createPredefinedNamespace(project, %22local%22, %22http://www.w3.org/2005/xquery-local-functions%22);%0A        %7D%0A        return predefinedNamespaces;%0A    %7D%0A%0A    private void createPredefinedNamespace(Project project, String prefix, String uri) %7B%0A        PsiElement prefixE
 leme
@@ -3081,28 +3081,23 @@
 mpl(
-getP
+p
 roject
-(), string
+, prefix
 );%0A 
@@ -3107,74 +3107,164 @@
     
-    strings.put(string, element);%0A        %7D%0A        return element
+PsiElement uriElement = new TextPsiElementImpl(project, uri);%0A        predefinedNamespaces.put(prefix, new XQueryNamespace(prefixElement, uriElement, this))
 ;%0A  

Rework XQueryModulePsiImpl to use a predefined namespaces map.