/* Banana-Chat - The first Open Source Knuddels Emulator
 * Copyright (C) 2011 - 2012 Flav <http://banana-coding.com>
 * 
 * Diese Dateien unterliegen dem Coprytight von Banana-Coding und
 * darf verändert, aber weder in andere Projekte eingefügt noch
 * reproduziert werden.
 * 
 * Der Emulator dient - sofern der Client nicht aus Eigenproduktion
 * stammt - nur zu Lernzwecken, das Hosten des originalen Knuddels Clients
 * ist auf eigene Gefahr und verstößt möglicherweise gegen Schutzrechte
 * der Knuddels.de GmbH & Co KG
 * 
 * Autoren: Flav (Grundversion), Localhost (Erweiterte Version), Kokos-Ice (Erweiterte Version)
 */



package tools;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import netchat.Channel;
import netchat.Client;
import netchat.Server;

public class KCodeParser {
	
	public static String clearKCode(String text) {
		return text.replace("§", "").replace("\\", "");
	}
	
    public static String parse(Client client, String str, int maxLineBreaks, int minSize, int maxSize) {
        StringBuilder ret = new StringBuilder();
        StringBuilder code = null;
        boolean isCode = false;
        boolean escape = false;
        byte lineBreaks = 0;

        
        for (int i = 0; i < str.length(); i++) {
            char current = str.charAt(i);

            if (current == '°' && !escape) {
                isCode = !isCode;

                if (isCode) {
                    if (str.lastIndexOf('°') == i) {
                        break;
                    }

                    code = new StringBuilder();
                } else {
                	if (!code.toString().isEmpty()) {
                    	if(!client.hasPermission("kcode.use")) {
                    		StringBuilder filtered = new StringBuilder();
                    		StringBuilder rgb = null;
                    		boolean isRGB = false;
                    		String size;

                    		for (int j = 0; j < code.length(); j++) {
                    			char c = code.charAt(j);

                    			if (isRGB) {
                    				if (c == ']') {
                    					if (!validateRGB(rgb.toString().split(","))) {
                    						break;
                    					}

                    					isRGB = false;
                    					filtered.append('[');
                    					filtered.append(rgb);
                    					filtered.append(']');
                    				} else if (isNumber(c) || c == ',') {
                    					rgb.append(c);
                    				} else {
                    					break;
                    				}
                    			} else {
                    				if (isNumber(c)) {
                    					size = "";

                    					while (j < code.length()) {
                    						c = code.charAt(j);

                    						if (!isNumber(c)) {
                    							j--;
                    							break;
                    						}

                    						size += c;
                    						j++;
                    					}

                    					if (Integer.parseInt(size) < minSize) {
                    						size = String.valueOf(minSize);
                    					} else if (Integer.parseInt(size) > maxSize) {
                    						size = String.valueOf(maxSize);
                    					}

                    					filtered.append(size);
                    				} else if (isColor(c) || c == 'r') {
                    					filtered.append(c);
                    				} else if (c == '[') {
                    					isRGB = true;
                    					rgb = new StringBuilder();
                    				} else {
                    					break;
                    				}
                    			}
                    		}

                    		if (filtered.toString().isEmpty()) {
                    			continue;
                    		}

                    		code = filtered;
                    	}

                    	ret.append('°');
                    	ret.append(code);
                    	ret.append('°');
                    }
                }

                continue;
            }

            if (isCode) {
                code.append(current);
            } else {
                if (current == '#' && !escape) {
                    if (lineBreaks < maxLineBreaks) { // !filter || vor lineBreaks
                        ret.append("#°!°");
                        lineBreaks++;
                    } else {
                        ret.append(' ');
                    }
                } else {
                    ret.append(current);
                }
            }

            if (current == '\\') {
                escape = !escape;
            } else {
                escape = false;
            }
        }
        
        if(client.getRank() > 0) {
        	String string = ret.toString();
        	
        	if(string.contains("°>/w")) {
        		ret.setLength(0);
        		Pattern pattern2 = Pattern.compile("\\°>\\/w (.+?)<\\°");
        		Matcher matcher = pattern2.matcher(string);
        	
        		while (matcher.find()) {
        			String var = matcher.group();
        			String nick = var.substring(var.indexOf("°>/w ")+5).split("<°")[0];
        			Client target2 = Server.get().getClient(nick);
        	         
        			if (target2 == null) {
        				target2 = new Client(null);
        				target2.loadStats(nick);
        	        }
        	         
        			String nick2 = target2.getName();
        	       
        			if (nick2 != null) {
        				string = string.replace("°>/w "+nick+"<°",String.format("°>linkicons/link-icon_whois...b.png<>--<>%s|/w %s<°", target2.getName(),target2.getName()));
        			} else {
        	    	   string = string.replace("°>/w "+nick+"<°","");
        			}
        		}

        		ret.append(string);
        		ret.append(' ');
        	}
        	
        	if(string.contains("°>/info")) {
        		ret.setLength(0);
        		Pattern pattern = Pattern.compile("\\°>\\/info (.+?)<\\°");
        		Matcher matcher2 = pattern.matcher(string);
        		
        		while (matcher2.find()) {
        			String var = matcher2.group();
        		    String channel = var.substring(var.indexOf("°>/info ")+8).split("<°")[0];
        		    Channel channelTo = Server.get().getChannel(channel);
        		     
        		    if (channelTo != null) {
        		    	string = string.replace("°>/info "+channel+"<°",String.format("°>linkicons/link-icon_channelinfo...b.png<>--<>%s|/info %s<°", channelTo.getName(),channelTo.getName()));
        		    } else {
        		    	string = string.replace("°>/info "+channel+"<°","");
        		    }
        		}

        		ret.append(string);
        		ret.append(' ');
        	}
        	
        	if(string.contains("°>/h")) {
        		ret.setLength(0);
        		Pattern pattern = Pattern.compile("\\°>\\/h (.+?)<\\°");
        		Matcher matcher2 = pattern.matcher(string);
        		
        		while (matcher2.find()) {
        			String var = matcher2.group();
        		    String channel = var.substring(var.indexOf("°>/h ")+5).split("<°")[0];
        		     
        		    if (Server.help.containsKey(channel)) {
        		    	string = string.replace("°>/h "+channel+"<°",String.format("°>linkicons/link-icon_hilfe...b.png<>--<>%s|/h %s<°", channel,channel));
        		    } else {
        		    	string = string.replace("°>/h "+channel+"<°","");
        		    }
        		}

        		ret.append(string);
        		ret.append(' ');
        	}
        	
    	    ret.setLength(0);
    	    string = string.replace("°>/m<°",String.format("°>linkicons/link-icon_post...b.png<>--<>|/m %s<°", client.getName()));
    	    ret.append(string);
    	    ret.append(' ');
    	        
        	String[] split = ret.toString().split(" ");
        	ret.setLength(0);

    		for (int i = 0; i < split.length; i++) {
        		String word = split[i].toLowerCase();
        	        
        		 if (word.startsWith("http://") || word.startsWith("https://") || word.startsWith("www.")) {
        			 String icon;
        			 
        			 if (split[i].contains("youtube.com")) {
        				 icon = "youtube";
        			 } else if (split[i].contains("knuddels-wiki.de")) {
        				 icon = "knuddels-wiki";
        			 } else if (split[i].contains(String.format("%sshop", Server.get().getURL()))) {
        				 icon = "shop";
        			 } else  if (split[i].contains(String.format("%sforum", Server.get().getURL()))) {
        				 icon = "forum";
        			 } else {
        				 icon = "default";
        			 }
        		
        			 split[i] = String.format("°>linkicons/link-icon_%s...b.png<>--<>%s|\"<°", icon,KCodeParser.escape(split[i]).replace("\\°!\\°", ""));
        		}

        		ret.append(split[i]);
        		ret.append(' ');
    		}
        }

        return ret.toString().trim();
    }

    public static String escape(String message) {
        return message.replace("\\", "\\\\").replace("\"", "\\\"").replace("#", "\\#").replace("_", "\\_").replace("§", "\\§").replace("°", "\\°").trim();
    }
    
    public static String noKCode(String message) {
    	return message.replaceAll("°[^°]+°", "").replace("°", "").replace("\"", "").replace("_", "").replace("#", "").replace("§", "").replace("\\", "");
    }

    private static boolean isNumber(int character) {
        return character >= '0' && character <= '9';
    }

    private static boolean isColor(int character) {
        switch (character) {
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case 'E':
            case 'G':
            case 'K':
            case 'L':
            case 'M':
            case 'N':
            case 'O':
            case 'P':
            case 'R':
            case 'W':
            case 'Y':
                return true;
            default:
                return false;
        }
    }

    private static boolean validateRGB(String[] rgb) {
        if (rgb.length < 3) {
            return false;
        }

        for (String color : rgb) {
            if (color.isEmpty() || color.length() > 3) {
                return false;
            }

            short value = Short.parseShort(color);

            if (value < 0 || value > 255) {
                return false;
            }
        }

        return true;
    }
}