/*
 * Paraselene
 * Copyright (c) 2009, 2010  Akira Terasaki
 * このファイルは同梱されているLicense.txtに定めた条件に同意できる場合にのみ
 * 利用可能です。
 */
package paraselene.mockup;

import java.util.*;
import java.net.*;
import paraselene.*;
import paraselene.tag.*;
import paraselene.css.*;
import paraselene.supervisor.*;

public class Converter {

	private static String[] uri_name = new String[] {
		"href", "codebase", "src", "cite", "action", "profile", "background",
		"code", "data",
	};
	private static String[] clr_name = new String[] {
		"color", "bgcolor", "text", "link", "vlink", "alink",
		"bordercolor", "bordercolordark", "bordercolorlight",
	};
	private static String[]	len_name = new String[] {
		"height", "hspace", "vspace", "width", "size", "units", "tabindex",
		"marginheight", "marginwidth", "topmargin", "leftmargin", "bottommargin",
		"rightmargin", "border", "framespacing",
		"charoff", "span", "colspan", "rowspan",
		"left", "pagex", "pagey", "top", "z-index", "loop",
		"scrollamount", "scrolldelay",
		"gutter",
		"cellpadding", "cellspacing", "datapagesize",
		"maxlength",
	};
	private static String[] mul_name = new String[] {
		"cols", "rows", "clip",
	};
	private static HashMap<String,String>	uri_map = new HashMap<String,String>();
	private static HashMap<String,String>	len_map = new HashMap<String,String>();
	private static HashMap<String,String>	mul_map = new HashMap<String,String>();
	private static HashMap<String,String>	clr_map = new HashMap<String,String>();
	static {
		for ( int i = 0; i < uri_name.length; i++ ) {
			uri_map.put( uri_name[i], uri_name[i] );
		}
		for ( int i = 0; i < len_name.length; i++ ) {
			len_map.put( len_name[i], len_name[i] );
		}
		for ( int i = 0; i < mul_name.length; i++ ) {
			mul_map.put( mul_name[i], mul_name[i] );
		}
		for ( int i = 0; i < clr_name.length; i++ ) {
			clr_map.put( clr_name[i], clr_name[i] );
		}
	}

	/**
	 * URI属性であるか？
	 * @param n 属性名。
	 * @return true:URI属性、false:URI属性ではない。
	 */
	static boolean isURI( String n ) {
		return ( uri_map.get( n.toLowerCase( Locale.ENGLISH ) ) != null );
	}
	/**
	 * 値を表す属性であるか？
	 * @param n 属性名。
	 * @return true:値を表す、false:値ではない。
	 */
	static boolean isNumber( String n ) {
		return ( len_map.get( n.toLowerCase( Locale.ENGLISH ) ) != null );
	}
	static boolean isMultiNumber( String n ) {
		return ( mul_map.get( n.toLowerCase( Locale.ENGLISH ) ) != null );
	}
	/**
	 * 色属性であるか？
	 * @param n 属性名。
	 * @return true:色属性、false:色属性ではない。
	 */
	static boolean isColor( String n ) {
		return ( clr_map.get( n.toLowerCase( Locale.ENGLISH ) ) != null );
	}
	static boolean isStyle( String n ) {
		return "style".equals( n.toLowerCase( Locale.ENGLISH ) );
	}

	public static AttributeValuable[] toAttributeValuable( String name, Valuable[] v, String dec ) {
		if ( v == null )	return new AttributeValuable[0];
		AttributeValuable[]	ret = new AttributeValuable[v.length];
		for ( int i = 0; i < v.length; i++ ) {
			AttributeValuable	txt = toAttributeValuable( v[i] );
			if ( txt == null )	return null;
			if ( isURI( name ) ) {
				if ( txt instanceof URIValue ) {
					ret[i] = txt;
					continue;
				}
				try {
					ret[i] = new URIValue( txt.toString() );
					continue;
				}
				catch( Exception e ) {
					Option.debug( e );
				}
			}
			else if ( isNumber( name ) || isMultiNumber( name ) ) {
				if ( txt instanceof NumberValue ) {
					ret[i] = txt;
					continue;
				}
				ret[i] = new NumberValue( txt.toString() );
				continue;
			}
			else if ( isColor( name ) ) {
				if ( txt instanceof Color ) {
					ret[i] = txt;
					continue;
				}
				ret[i] = new Color( txt.toString() );
				continue;
			}
			else if ( isStyle( name ) ) {
				if ( txt instanceof Style ) {
					ret[i] = txt;
					continue;
				}
				ret[i] = new Style( Property.create( txt.toString(), dec ) );
				continue;
			}
			ret[i] = txt;
		}
		return ret;
	}

	public static AttributeValuable[] toAttributeValuable( String name, String txt, String dec ) {
		if ( txt == null )	return null;
		String[]	part = null;
		if ( isMultiNumber( name ) ) {
			part = txt.split( "," );
		}
		else {
			part = new String[]{ txt };
		}
		AttributeValuable[]	ret = new AttributeValuable[part.length];
		for ( int  i = 0; i < part.length; i++ ) {
			if ( isURI( name ) ) {
				try {
					ret[i] = new URIValue( part[i] );
					continue;
				}
				catch( Exception e ) {
					Option.debug( e );
				}
			}
			else if ( isNumber( name ) || isMultiNumber( name ) ) {
				ret[i] = new NumberValue( part[i] );
				continue;
			}
			else if ( isColor( name ) ) {
				ret[i] = new Color( part[i] );
				continue;
			}
			else if ( isStyle( name ) ) {
				ret[i] = new Style( Property.create( part[i], dec ) );
				continue;
			}
			ret[i] = new Text( part[i] );
		}
		return ret;
	}

	private static AttributeValuable toAttributeValuable( Valuable v ) {
		if ( v == null )	return null;
		if ( v instanceof WebColor ) {
			return new Color( ((WebColor)v).toString() );
		}
		if ( v instanceof Infinite ) {
			return new NumberValue( (Infinite)v );
		}
		if ( v instanceof AttributeValuable ) {
			return (AttributeValuable)v;
		}
		Option.debug( "unknown class " + v.getClass().toString() );
		return null;
	}

	public static CSSValuable toCSSValuable( String txt, String dec ) {
		try {
			return new Color( txt );
		}
		catch( Exception e ){}
		try {
			return new NumberValue( txt );
		}
		catch( Exception e ){}
		if ( URIValue.isCSSURL( txt ) ) {
			txt = URIValue.CSSURLStrip( txt );
			try {
				return new URIValue( new URI( txt ), dec, null );
			}
			catch( Exception e ){
				try {
					return new URIValue( txt );
				}
				catch( Exception ee ) {
					Option.debug( ee );
				}
			}
		}
		return new Text( txt );
	}

	private static CSSValuable toCSSValuable( Valuable v ) {
		AttributeValuable	atb = toAttributeValuable( v );
		if ( atb == null )	return null;
		if ( atb instanceof CSSValuable ) {
			return (CSSValuable)atb;
		}
		Option.debug( "unknown class " + v.getClass().toString() );
		return null;
	}

	public static CSSValuable[] toCSSValuable( Valuable[] v ) {
		if ( v == null )	return new CSSValuable[0];
		ArrayList<CSSValuable>	ret = new ArrayList<CSSValuable>();
		for ( int i = 0; i < v.length; i++ ) {
			CSSValuable	tmp = toCSSValuable( v[i] );
			if ( tmp != null )	ret.add( tmp );
		}
		return ret.toArray( new CSSValuable[0] );
	}
}

