package org.elmlang.intellijplugin.psi.references.utils;

import com.intellij.psi.PsiElement;
import org.elmlang.intellijplugin.psi.ElmFile;
import org.elmlang.intellijplugin.psi.ElmTreeUtil;
import org.elmlang.intellijplugin.psi.ElmUpperCaseId;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

public class AbsoluteReferencesHelper {
    @Nullable
    public static <T extends PsiElement> PsiElement resolveAbsoluteReference(List<ElmUpperCaseId> moduleName, Function<ElmFile, Optional<T>> resolver) {
        PsiElement psiElement = getModuleNames(moduleName)
                .map(name -> ModuleIndexHelper.resolveUsingModuleIndex(
                        name,
                        moduleName.get(0).getProject(),
                        resolver))
                .filter(e -> e != null)
                .findFirst()
                .orElse(null);
        if (psiElement == null) {
            return null;
        }
        return psiElement;
    }

    private static Stream<String> getModuleNames(List<ElmUpperCaseId> upperCaseIdList) {
        return getModuleNamesAsLists(upperCaseIdList)
                .map(ElmTreeUtil::joinUsingDot);
    }

    private static Stream<List<ElmUpperCaseId>> getModuleNamesAsLists(List<ElmUpperCaseId> upperCaseIdList) {
        return Stream.concat(
                Stream.of(upperCaseIdList),
                getAliasedModules(upperCaseIdList));
    }

    private static Stream<List<ElmUpperCaseId>> getAliasedModules(List<ElmUpperCaseId> upperCaseIdList) {
        if (upperCaseIdList.size() == 1) {
            ElmUpperCaseId elem = upperCaseIdList.get(0);
            ElmFile file = (ElmFile) elem.getContainingFile();
            return file.getImportClausesByAlias(elem.getText())
                    .map(e -> e.getModuleName().getUpperCaseIdList());
        }
        return Stream.empty();
    }
}

@@ -239,16 +239,76 @@
 CaseId;%0A
+import org.elmlang.intellijplugin.psi.scope.ElmCoreLibrary;%0A
 import o
@@ -1314,16 +1314,244 @@
 singDot)
+%0A                .filter(name -%3E%0A                        ElmCoreLibrary.isImplicitImport(name)%0A                                %7C%7C getContainingFile(upperCaseIdList).getImportClauseByModuleName(name).isPresent()%0A                )
 ;%0A    %7D%0A
@@ -1960,27 +1960,20 @@
     
-ElmUpperCaseId elem
+String alias
  = u
@@ -1993,16 +1993,26 @@
 t.get(0)
+.getText()
 ;%0A      
@@ -2021,82 +2021,49 @@
     
-ElmFile file = (ElmFile) elem.getContainingFile();%0A            return file
+return getContainingFile(upperCaseIdList)
 .get
@@ -2087,22 +2087,13 @@
 ias(
-elem.getText()
+alias
 )%0A  
@@ -2207,11 +2207,208 @@
 );%0A    %7D
+%0A%0A    private static ElmFile getContainingFile(List%3CElmUpperCaseId%3E upperCaseIdList) %7B%0A        ElmUpperCaseId elem = upperCaseIdList.get(0);%0A        return (ElmFile) elem.getContainingFile();%0A    %7D
 %0A%7D%0A

Fix of resolving absolute references.