package com.github.games647.colorconsole.common;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import java.util.Collection;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.apache.logging.log4j.core.pattern.AnsiEscape;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.Ansi.Attribute;
import org.fusesource.jansi.AnsiRenderer;

public class CommonFormatter {

    private final String reset = Ansi.ansi().a(Ansi.Attribute.RESET).toString();

    private final Set<String> ignoreMessages;
    private final boolean colorizeTag;
    private final boolean truncateColor;
    private Map<String, String> pluginColors;

    public CommonFormatter(Collection<String> ignoreMessages, boolean colorizeTag, boolean truncateColor) {
        this.ignoreMessages = ImmutableSet.copyOf(ignoreMessages);
        this.colorizeTag = colorizeTag;
        this.truncateColor = truncateColor;
    }

    public boolean shouldIgnore(String message) {
        for (String ignore : ignoreMessages) {
            if (message.contains(ignore)) {
                return true;
            }
        }

        return false;
    }

    public void initPluginColors(Collection<String> plugins, Map<String, String> configColors, String def) {
        Random random = new Random();
        Ansi.Color[] colors = Ansi.Color.values();

        ImmutableMap.Builder<String, String> colorBuilder = ImmutableMap.builder();
        for (String plugin : plugins) {
            String styleCode = configColors.getOrDefault(plugin, def);
            if (styleCode.equalsIgnoreCase("random")) {
                //ignore default
                styleCode = colors[random.nextInt(colors.length - 1)].name();
            }

            colorBuilder.put(plugin, format(styleCode));
        }

        this.pluginColors = colorBuilder.build();
    }

    public String colorizePluginTag(String message) {
        if (!message.contains("[") || !message.contains("]")) {
            return message;
        }

        String newMessage = message;

        String startingColorCode = "";
        if (message.startsWith(AnsiEscape.CSI.getCode())) {
            int endColor = message.indexOf(AnsiEscape.SUFFIX.getCode());

            newMessage = message.substring(endColor + 1, message.length());
            if (!truncateColor) {
                startingColorCode = message.substring(0, endColor + 1);
            }
        }

        int startTag = newMessage.indexOf('[') + 1;
        int endTag = newMessage.indexOf(']', startTag);

        String pluginName = colorizePluginName(newMessage.substring(startTag, endTag));
        return '[' + pluginName + ']' + startingColorCode + newMessage.substring(endTag + 1);
    }

    public String colorizePluginName(String pluginName) {
        if (!colorizeTag) {
            return pluginName;
        }

        String pluginColor = pluginColors.getOrDefault(pluginName, "");
        return pluginColor + pluginName + reset;
    }

    public String format(String pluginFormat) {
        String[] formatParts = pluginFormat.split(" ");
        Ansi ansi = Ansi.ansi();
        for (String format : formatParts) {
            for (AnsiRenderer.Code ansiCode : AnsiRenderer.Code.values()) {
                if (ansiCode.name().equalsIgnoreCase(format)) {
                    if (ansiCode.isAttribute()) {
                        ansi.a(ansiCode.getAttribute());
                    } else if (ansiCode.isBackground()) {
                        ansi.bg(ansiCode.getColor());
                    } else {
                        ansi.fg(ansiCode.getColor());
                    }
                }
            }

            if ("blink".equalsIgnoreCase(format)) {
                ansi.a(Attribute.BLINK_SLOW);
                continue;
            }

            if ("strikethrough".equalsIgnoreCase(format)) {
                ansi.a(Attribute.STRIKETHROUGH_ON);
                continue;
            }

            if ("hidden".equalsIgnoreCase(format)) {
                ansi.a(Attribute.CONCEAL_OFF);
                continue;
            }

            if ("dim".equalsIgnoreCase(format)) {
                ansi.a(Attribute.INTENSITY_FAINT);
                continue;
            }

            if ("reverse".equalsIgnoreCase(format)) {
                ansi.a(Attribute.NEGATIVE_ON);
                continue;
            }

            for (Ansi.Color color : Ansi.Color.values()) {
                if (format.equalsIgnoreCase(color.name())) {
                    ansi.fg(color);
                    break;
                }
            }
        }

        return ansi.toString();
    }

    public String getReset() {
        return reset;
    }
}

@@ -241,65 +241,8 @@
 t;%0A%0A
-import org.apache.logging.log4j.core.pattern.AnsiEscape;%0A
 impo
@@ -271,16 +271,16 @@
 i.Ansi;%0A
+
 import o
@@ -390,16 +390,204 @@
 tter %7B%0A%0A
+    //copied from AnsiEscape in order to provide compatibility with older minecraft versions%0A    private static final String CSI = %22%5Cu001b%5B%22;%0A    private static final String SUFFIX = %22m%22;%0A
     priv
@@ -2293,32 +2293,11 @@
 ith(
-AnsiEscape.CSI.getCode()
+CSI
 )) %7B
@@ -2344,35 +2344,14 @@
 xOf(
-AnsiEscape.SUFFIX.getCode()
+SUFFIX
 );%0A%0A

Fix compatibility with Minecraft 1.11