JSocketMUD/
JSocketMUD/dk/socketmud/
JSocketMUD/dk/socketmud/io/
JSocketMUD/dk/socketmud/object/
JSocketMUD/dk/socketmud/util/
package dk.socketmud.util;

public class Format
{
	private static final String AnsiCodes = "unrRgGpPcCdDwWbByY";
	private static final String ReplaceCodes = "#";

	public static String cprintf(String fmt, Object ... varargs)
	{
		return cprintf(fmt.toCharArray(), varargs);
	}
	
	public static String cprintf(char[] fmt, Object ... varargs)
	{
		StringBuffer buf = new StringBuffer();
		int i = 0;
		int len = fmt.length;
		int argc = 0;

		while (i < len)
		{
			boolean reverse = false;
			int size = 0;
			int maxSize = 0;
			
			switch (fmt[i])
			{
				default:
					buf.append(fmt[i++]);
					break;
				case '%':
					// should we align this in reverse?
					if (fmt[i + 1] == '-')
					{
						i++;
						reverse = true;
					}

					// get the size, if any
					while (Character.isDigit(fmt[i + 1]))
					{
						i++;
						size *= 10;
						size += fmt[i] - '0';
					}

					// any size restrictions?
					if (fmt[i + 1] == '.')
					{
						i++;
						while (Character.isDigit(fmt[i + 1]))
				        {
							i++;
							maxSize *= 10;
							maxSize += fmt[i] - '0';
				        }
					}

					i++;
					switch (fmt[i])
					{
						default:
							buf.append('%');
							break;
						case 's':
							String s = (String) getVarArg(fmt[i], argc, varargs);
							if (maxSize > 0)
								s = restrictString(s, maxSize);
							size -= colourLength(s);
							argc++;

							if (!reverse)
							{
								while(size-- > 0)
									buf.append(' ');
							}

							buf.append(s);

							if (reverse)
							{
								while(size-- > 0)
									buf.append(' ');
							}
							i++;
							break;
						case 'd':
				      	    int value = (Integer) getVarArg(fmt[i], argc, varargs);
				      	    argc++;

				      	    // a little trick to see how long the number is
				      	    String tmp = "" + value;
				      	    size -= tmp.length();

				      	    if (!reverse)
				      	    {
				      	    	while(size-- > 0)
				      	    		buf.append(' ');
				      	    }

				      	    buf.append(tmp);

				      	    if (reverse)
				      	    {
				      	    	while(size-- > 0)
				      	    		buf.append(' ');
				      	    }
				      	    i++;
				      	    break;
					}
					break;
			}
		}

		return buf.toString();
	}
		
	private static Object getVarArg(char type, int num, Object ... varargs) throws IllegalArgumentException
	{
		if (varargs.length < (num + 1))
			throw new IllegalArgumentException("Not enough variable arguments");

		Object o = varargs[num];
		
		switch (type)
		{
			default:
				throw new IllegalArgumentException("Unknown type '" + type + "'");
			case 's':
				if (o instanceof String)
					break;
				else
					throw new IllegalArgumentException("variable argument " + (num + 1) + " not of type String");
			case 'd':
				if (o instanceof Integer)
					break;
				else
					throw new IllegalArgumentException("variable argument " + (num + 1) + " not of type Integer");
		}

		return o;
	}
	
	public static String restrictString(String s, int maxSize)
	{
		StringBuffer buf = new StringBuffer();
		char[] c = s.toCharArray();
		boolean done = false;
		int size = s.length();
		int len = 0;
		int i = 0;

		while (i < size && !done)
		{
		    boolean found = false;

		    switch (c[i])
		    {
		    	default:
		    		if (++len > maxSize)
		    		{
		    			done = true;
		    			break;
		    		}
		    		buf.append(c[i]);
		    		i++;
	    			break;
		    	case '#':
		    		i++;
		    		if (AnsiCodes.indexOf(c[i]) > -1)
		    		{
		    			buf.append('#');
		    			buf.append(c[i]);
		    			i++;
		    			found = true;
		    		}
		    		
		    		if (!found && ReplaceCodes.indexOf(c[i]) > - 1)
	    			{
	    				if (++len > maxSize)
	    				{
	    					done = true;
	    					break;
	    				}
	    				buf.append('#');
	    				buf.append(c[i]);
	    				found = true;
		    		}

		    		if (!found)
		    		{
		    			if (++len > maxSize)
		    			{
		    				done = true;
		    				break;
		    			}
		    			buf.append('#');
		    		}
		    		break;
		    }
		}

		return buf.toString();
	}
	
	private static int colourLength(String s)
	{
		char[] c = s.toCharArray();
		int len = 0;
		int max = s.length();
		int i = 0;

		while (i < max)
		{
		    boolean found = false;

		    switch(c[i])
		    {
		    	default:
		    		len++;
		    		i++;
		    		break;
		    	case '#':
		    		i++;
		    		if (AnsiCodes.indexOf(c[i]) > -1)
		    		{
		    			i++;
		    			found = true;
		    		}
		    		
		    		if (!found && ReplaceCodes.indexOf(c[i]) > - 1)
		    		{
		    			len++;
		    			i++;
		    			found = true;
		    		}
		    	  
		    		if (!found)
		    			len++;
		    		break;
		    }
		}

		return len;
	}
}