/*
 * This file is part of Sponge, licensed under the MIT License (MIT).
 *
 * Copyright (c) SpongePowered <https://www.spongepowered.org>
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.spongepowered.vanilla.chat;

import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.util.text.event.ClickEvent;

import javax.annotation.Nullable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class ChatFormatter {

    private static final String DEFAULT_SCHEME = "http://";

    private static final String SCHEME = "https?://";
    private static final String IP_ADDRESS = "(?:\\d{1,3}\\.){3}\\d{1,3}";
    private static final String DOMAIN = "(?:[a-z\\d](?:[a-z\\d-]*[a-z\\d])?\\.)+[a-z](?:[a-z\\d-]*[a-z\\d])?";
    private static final String PORT = "\\d{1,5}";
    private static final String PATH = ".*?";

    private static final Pattern URL_PATTERN = Pattern.compile(
            "(?:" + ChatFormatter.SCHEME + ")?(?:" + ChatFormatter.IP_ADDRESS + '|' + ChatFormatter.DOMAIN + ")(?::" + ChatFormatter.PORT + ")?" + ChatFormatter.PATH + "(?=[!?,;:\"']?(?:[§\\s]|$))",
            Pattern.CASE_INSENSITIVE);

    private ChatFormatter() {
    }

    public static void formatChatComponent(TranslationTextComponent component) {
        String message = (String) component.getFormatArgs()[1];
        ITextComponent formatted = ChatFormatter.format(message);
        if (formatted == null) {
            return;
        }

        formatted.getStyle().setParentStyle(component.getStyle());
        component.getFormatArgs()[1] = formatted;
    }

    @Nullable
    public static ITextComponent format(String s) {
        Matcher matcher = ChatFormatter.URL_PATTERN.matcher(s);
        if (!matcher.find()) {
            return null;
        }

        ITextComponent result = null;

        int pos = 0;
        do {
            int start = matcher.start();
            int end = matcher.end();

            String displayUrl = s.substring(start, end);
            String url = displayUrl;

            try {
                if (new URI(url).getScheme() == null) {
                    url = ChatFormatter.DEFAULT_SCHEME + url;
                }
            } catch (URISyntaxException e) {
                continue; // Invalid URL so just ignore it
            }

            if (pos < start) {
                if (result == null) {
                    result = new StringTextComponent(s.substring(pos, start));
                } else {
                    result.appendText(s.substring(pos, start));
                }
            }

            pos = end;

            ITextComponent link = new StringTextComponent(displayUrl);
            link.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url));

            if (result == null) {
                result = new StringTextComponent("");
            }

            result.appendSibling(link);

        } while (matcher.find());

        // If there is something left, append the rest
        if (pos < s.length()) {
            if (result == null) {
                result = new StringTextComponent(s.substring(pos));
            } else {
                result.appendText(s.substring(pos));
            }
        }

        return result;
    }

}

@@ -1278,24 +1278,82 @@
 illa.chat;%0A%0A
+import net.minecraft.util.text.IFormattableTextComponent;%0A
 import net.m
@@ -2521,16 +2521,22 @@
 mponent(
+final 
 Translat
@@ -2569,24 +2569,30 @@
 ) %7B%0A        
+final 
 String messa
@@ -2610,38 +2610,32 @@
 g) component.get
-Format
 Args()%5B1%5D;%0A     
@@ -2629,32 +2629,38 @@
 s()%5B1%5D;%0A        
+final 
 ITextComponent f
@@ -2777,93 +2777,20 @@
     
-formatted.getStyle().setParentStyle(component.getStyle());%0A        component.getForma
+component.ge
 tArg
@@ -2870,16 +2870,22 @@
  format(
+final 
 String s
@@ -2896,16 +2896,22 @@
         
+final 
 Matcher 
@@ -3026,32 +3026,43 @@
     %7D%0A%0A        I
+Formattable
 TextComponent re
@@ -3117,24 +3117,30 @@
             
+final 
 int start = 
@@ -3164,24 +3164,30 @@
             
+final 
 int end = ma
@@ -3208,24 +3208,30 @@
             
+final 
 String displ
@@ -3476,16 +3476,22 @@
  catch (
+final 
 URISynta
@@ -3778,36 +3778,32 @@
    result.append
-Text
 (s.substring(pos
@@ -3882,17 +3882,34 @@
         
-I
+final IFormattable
 TextComp
@@ -3970,16 +3970,30 @@
         
+link.setStyle(
 link.get
@@ -4000,19 +4000,20 @@
 Style().
-set
+with
 ClickEve
@@ -4063,16 +4063,17 @@
 L, url))
+)
 ;%0A%0A     
@@ -4199,15 +4199,8 @@
 pend
-Sibling
 (lin
@@ -4478,20 +4478,16 @@
 t.append
-Text
 (s.subst

update ChatFormatter