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

import paraselene.*;
import paraselene.tag.*;
import java.util.*;


/**
 * カスケードスタイルシートの１スタイル。
 */
public class Style extends HTMLPart implements AttributeValuable {
	private static final long serialVersionUID = 2L;

	private ArrayList<Selector>	selector = new ArrayList<Selector>();
	private ArrayList<Property> prop = new ArrayList<Property>();
	private HashMap<String, Property>   map = new HashMap<String, Property>();

	private Style(){}
	/**
	 * コンストラクタ。
	 */
	public Style( Property ... p ) {
		setProperty( p );
	}

	public void setAssignedTag( Tag t ) {
		super.setAssignedTag( t );
		if ( prop == null )	return;
		int cnt = prop.size();
		for ( int i = 0; i < cnt; i++ ) {
			prop.get( i ).setAssignedTag( t );
		}
	}

	public HTMLPart getReplica() {
		return (HTMLPart)getValuableReplica();
	}

	public Valuable getValuableReplica() {
		int	cnt = prop.size();
		Property[]	p = new Property[cnt];
		for ( int i = 0; i < cnt; i++ ) {
			p[i] = prop.get( i ).getReplica();
		}
		Style	style = new Style( p );

		cnt = selector.size();
		Selector[]	s = new Selector[cnt];
		for ( int i = 0; i < cnt; i++ ) {
			s[i] = selector.get( i ).getReplica();
		}
		style.setSelector( s );
		return style;
	}

	/**
	 * セレクタの設定。
	 * @param s セレクタ。
	 */
	public void setSelector( Selector ... s ) {
		for ( int i = 0; i < s.length; i++ ) {
			selector.add( s[i] );
		}
		getAssignedTag().setModify();
	}

	/**
	 * 属性の設定。同じ属性があると上書きされます。
	 * @param p 属性。
	 */
	public void setProperty( Property ... p ) {
		for ( int i = 0; i < p.length; i++ ) {
			prop.add( p[i] );
			prop.remove( map.put( p[i].getName(), p[i] ) );
		}
		getAssignedTag().setModify();
	}

	/**
	 * 属性の削除。
	 * @param name 属性名。
	 */
	public void removeProperty( String name ) {
		prop.remove( map.remove( name ) );
		getAssignedTag().setModify();
	}

	/**
	 * 属性の取得。
	 * @param name 属性名。
	 */
	public Property getProperty( String name ) {
		return map.get( name );
	}

	/**
	 * 属性の全取得。属性の宣言順にソートされています。
	 */
	public Property[] getAllProperty() {
		return prop.toArray( new Property[0] );
	}

	public String toString( StringMode mode ) {
		StringBuilder	buf = new StringBuilder();
		int	sel_cnt = selector.size();
		if ( sel_cnt > 0 && mode != StringMode.ATTRIBUTE ) {
			for ( int i = 0; i < sel_cnt; i++ ) {
				buf = buf.append( selector.get( i ).toString() );
			}
			buf = buf.append( '{' );
		}
		int	cnt = prop.size();
		for ( int i = 0; i < cnt; i++ ) {
			buf = buf.append( prop.get( i ).toString() );
		}
		if ( sel_cnt > 0 && mode != StringMode.ATTRIBUTE ) {
			buf = buf.append( '}' );
		}
		return buf.toString();
	}
	
	public String toString() {
		return toString( StringMode.PLAIN );
	}
}

