package mnm.mods.tabbychat.extra.filters;

import mnm.mods.tabbychat.api.Channel;
import mnm.mods.tabbychat.api.TabbyAPI;
import mnm.mods.tabbychat.api.filters.Filter;
import mnm.mods.tabbychat.api.filters.FilterEvent;
import mnm.mods.tabbychat.api.filters.FilterSettings;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.text.ITextComponent;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.RegEx;

public class UserFilter implements Filter {

    private String name = "New Filter";
    private FilterSettings settings = new FilterSettings();
    private String pattern = ".*";

    private transient Pattern expression;

    public void setPattern(@RegEx String pattern) throws PatternSyntaxException {
        testPatternUnsafe(pattern);
        this.pattern = pattern;
        this.expression = null;
    }

    public void testPattern(String pattern) throws UserPatternException {
        try {
            testPatternUnsafe(pattern);
        } catch (PatternSyntaxException e) {
            throw new UserPatternException(e);
        }
    }

    private void testPatternUnsafe(String pattern) throws PatternSyntaxException {
        Pattern.compile(resolvePattern(pattern));
    }

    @Override
    public Pattern getPattern() {
        if (expression == null) {
            this.expression = Pattern.compile(resolvePattern(pattern), settings.getFlags());
        }
        return expression;
    }

    private String resolvePattern(String pattern) {
        String resolved = resolveVariables(pattern);
        if (!settings.isRegex()) {
            resolved = Pattern.quote(resolved);
        }
        return resolved;
    }

    public String getRawPattern() {
        return this.pattern;
    }

    @RegEx
    private static String resolveVariables(String pattern) {
        Matcher matcher = Pattern.compile("\\$\\{([\\w\\d]+)}").matcher(pattern);
        StringBuffer buffer = new StringBuffer();
        while (matcher.find()) {
            String key = matcher.group(1);
            String var = FilterAddon.getVariable(key);
            matcher.appendReplacement(buffer, var);
        }
        matcher.appendTail(buffer);

        return pattern;
    }

    @Override
    public void action(FilterEvent event) {

        if (settings.isRemove()) {
            // remove
            event.channels.clear();
        } else {
            // add channels
            for (String name : settings.getChannels()) {
                // replace group tokens in channel name
                Matcher matcher = Pattern.compile("\\$(\\d+)").matcher(name);
                while (matcher.find()) {
                    // find groups
                    int group = Integer.parseInt(matcher.group(1));
                    if (group > 0 && event.matcher.groupCount() >= group) {
                        String groupText = event.matcher.group(group);
                        if (groupText != null) {
                            name = name.replace(matcher.group(), groupText);
                            continue;
                        }
                    }
                    name = null;
                    break;
                }
                // skip this because there were missing or out of bounds groups.
                if (name == null)
                    continue;

                // PMs start with a '@' character
                boolean pm = name.startsWith("@");
                // remove # or @ from the start of the channel name
                if (name.startsWith("#") || name.startsWith("@"))
                    name = name.substring(1);

                Channel channel = TabbyAPI.getAPI().getChat().getChannel(name, pm);
                event.channels.add(channel);
            }
        }
        // play sound
        if (settings.isSoundNotification()) {
            settings.getSoundName()
                    .map(ResourceLocation::new)
                    .map(SoundEvent.REGISTRY::getObject)
                    .map(sndEvent -> PositionedSoundRecord.getMasterRecord(sndEvent, 1.0F))
                    .ifPresent(Minecraft.getMinecraft().getSoundHandler()::playSound);

        }
    }

    @Override
    public String prepareText(ITextComponent string) {
        return settings.isRaw() ? string.getFormattedText() : Filter.super.prepareText(string);
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public FilterSettings getSettings() {
        return settings;
    }

    class UserPatternException extends Exception {
        private UserPatternException(PatternSyntaxException e) {
            super(e);
        }
    }
}

@@ -2576,20 +2576,9 @@
    %7D
- else %7B%0A    
+%0A
     
@@ -2597,20 +2597,16 @@
 hannels%0A
-    
         
@@ -2658,28 +2658,24 @@
             
-  
-  
 // replace g
@@ -2694,36 +2694,32 @@
 in channel name%0A
-    
             Matc
@@ -2784,28 +2784,24 @@
             
-  
-  
 while (match
@@ -2829,20 +2829,16 @@
         
-    
 // find 
@@ -2860,20 +2860,16 @@
         
-  
-  
 int grou
@@ -2904,28 +2904,24 @@
 .group(1));%0A
-    
             
@@ -2996,28 +2996,24 @@
             
-  
-  
 String group
@@ -3059,36 +3059,32 @@
                 
-    
 if (groupText !=
@@ -3108,36 +3108,32 @@
                 
-  
-  
 name = name.repl
@@ -3181,36 +3181,32 @@
                 
-    
 continue;%0A      
@@ -3199,20 +3199,16 @@
 ntinue;%0A
-    
         
@@ -3233,32 +3233,26 @@
             
-    %7D%0A  
+%7D%0A
             
@@ -3247,34 +3247,32 @@
                 
-  
 name = null;%0A   
@@ -3268,20 +3268,16 @@
 = null;%0A
-    
         
@@ -3299,34 +3299,26 @@
             
-    %7D%0A    
+%7D%0A
             
@@ -3386,36 +3386,32 @@
 ps.%0A            
-  
-  
 if (name == null
@@ -3420,36 +3420,32 @@
                 
-    
 continue;%0A%0A     
@@ -3451,20 +3451,16 @@
         
-  
-  
 // PMs s
@@ -3485,20 +3485,16 @@
 aracter%0A
-    
         
@@ -3536,36 +3536,32 @@
 %22);%0A            
-  
-  
 // remove # or @
@@ -3600,36 +3600,32 @@
 ame%0A            
-    
 if (name.startsW
@@ -3666,36 +3666,32 @@
                 
-  
-  
 name = name.subs
@@ -3697,28 +3697,24 @@
 string(1);%0A%0A
-    
             
@@ -3785,36 +3785,32 @@
 m);%0A            
-  
-  
 event.channels.a
@@ -3822,30 +3822,16 @@
 annel);%0A
-            %7D%0A
         

Add support for filters which remove from * but also add to other channels