package name.kropp.intellij.makefile.psi;

import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.stream.Collectors;

public class MakefilePsiImplUtil {
    @Nullable
    public static String getTargetName(MakefileTargetLine element) {
        ASTNode targetNode = element.getNode().findChildByType(MakefileTypes.TARGET);
        if (targetNode == null) {
            return null;
        }
        return targetNode.getText();
    }

    @Nullable
    public static String getName(MakefileTarget element) {
        return element != null ? element.getText() : null;
    }

    public static PsiElement setName(MakefileTarget element, String newName) {
        ASTNode identifierNode = element.getNode().getFirstChildNode();
        if (identifierNode != null) {
            MakefileTarget target = MakefileElementFactory.INSTANCE.createTarget(element.getProject(), newName);
            ASTNode newIdentifierNode = target.getFirstChild().getNode();
            element.getNode().replaceChild(identifierNode, newIdentifierNode);
        }
        return element;
    }

    @Nullable
    public static PsiElement getNameIdentifier(MakefileTarget element) {
        ASTNode targetNode = element.getNode();
        return targetNode != null ? targetNode.getPsi() : null;
    }

    public static ItemPresentation getPresentation(MakefileTarget element) {
        return new MakefileTargetPresentation(element);
    }

    public static boolean isSpecialTarget(MakefileTarget element) {
        String name = element.getName();
        return name != null && (name.matches("^\\.[A-Z_]*") || name.equals("FORCE"));
    }

    public static boolean isPatternTarget(MakefileTarget element) {
        String name = element.getName();
        return name != null && name.contains("%");
    }

    public static boolean matches(MakefileTarget element, String prerequisite) {
        String name = element.getName();
        if (name == null) {
            return false;
        }
        if (name.startsWith("%")) {
            return prerequisite.endsWith(name.substring(1));
        }
        if (name.endsWith("%")) {
            return prerequisite.startsWith(name.substring(0, name.length()-1));
        }
        return name.equals(prerequisite);
    }

    private static TokenSet ASSIGNMENT = TokenSet.create(MakefileTypes.ASSIGN);
    private static TokenSet LINE = TokenSet.create(MakefileTypes.LINE);
    private static TokenSet VARIABLE_VALUE_LINE = TokenSet.create(MakefileTypes.VARIABLE_VALUE_LINE);

    @Nullable
    public static PsiElement getAssignment(MakefileVariableAssignment element) {
        ASTNode node = element.getNode().findChildByType(ASSIGNMENT);
        if (node == null)
            return null;
        return node.getPsi();
    }

    @Nullable
    public static String getValue(MakefileVariableAssignment element) {
        MakefileVariableValue value = element.getVariableValue();
        if (value == null) {
            return "";
        }
        ASTNode[] nodes = value.getNode().getChildren(LINE);
        return Arrays.stream(nodes).map(ASTNode::getText).collect(Collectors.joining("\n"));
    }

    @Nullable
    public static PsiElement getAssignment(MakefileDefine element) {
        ASTNode node = element.getNode().findChildByType(ASSIGNMENT);
        if (node == null)
            return null;
        return node.getPsi();
    }

    @Nullable
    public static String getValue(MakefileDefine element) {
        ASTNode[] nodes = element.getNode().getChildren(VARIABLE_VALUE_LINE);
        return Arrays.stream(nodes).map(ASTNode::getText).collect(Collectors.joining("\n"));
    }
}
@@ -284,62 +284,222 @@
 til.
-stream.Collectors;%0A%0Apublic class MakefilePsiImplUtil %7B
+regex.Matcher;%0Aimport java.util.regex.Pattern;%0Aimport java.util.stream.Collectors;%0A%0Apublic class MakefilePsiImplUtil %7B%0A    private static final Pattern suffixRule = Pattern.compile(%22%5E%5C%5C.%5Ba-zA-Z%5D+(%5C%5C.%5Ba-zA-Z%5D+)$%22);%0A
 %0A   
@@ -1950,16 +1950,54 @@
 %22FORCE%22)
+ %7C%7C suffixRule.matcher(name).matches()
 );%0A    %7D
@@ -2574,32 +2574,187 @@
 -1));%0A        %7D%0A
+        Matcher matcher = suffixRule.matcher(name);%0A        if (matcher.matches()) %7B%0A            return prerequisite.endsWith(matcher.group(1));%0A        %7D%0A
         return n

support old-fashioned suffix rules (like .c.o)