/*******************************************************************************
 * Copyright (c) 2004 Actuate Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *  Actuate Corporation  - initial API and implementation
 *******************************************************************************/

package org.eclipse.birt.report.engine.toc;

import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.birt.core.format.DateFormatter;
import org.eclipse.birt.core.format.NumberFormatter;
import org.eclipse.birt.report.engine.api.TOCNode;

import com.ibm.icu.util.ULocale;


public class TOCTreeNode extends TOCNode
{
	private boolean isGroupRoot;

	/**
	 * A set of formats under which this node should be hidden.
	 */
	protected Set hiddenFormats = null;
	
	protected String hiddenFormatsString;

	/**
	 * Flag indicatding that the node should be hidden under all format.
	 */
	protected boolean isAllHidden;
	
	/**
	 * Value of TOC.
	 */
	protected Object tocValue;
	
	public TOCTreeNode( )
	{
	}

	public TOCTreeNode( TOCNode node )
	{
		super( node );
	}

	public TOCTreeNode( TOCTreeNode node )
	{
		super( node );
		this.hiddenFormats = node.hiddenFormats;
		this.hiddenFormatsString = node.hiddenFormatsString;
		this.isGroupRoot = node.isGroupRoot;
		this.tocValue = node.tocValue;
	}

	public boolean isGroupRoot( )
	{
		return isGroupRoot;
	}

	public String getHiddenFormats( )
	{
		return this.hiddenFormatsString;
	}

	/**
	 * Adds some formats under which this node should be hidden. <br>
	 * The parameter <code>formats</code> is a string which contains all the
	 * formats. For example, if under "html" and "pdf" formats the report itme
	 * related with this toc node need to be hidden, the value of this variable
	 * should be "html, pdf"".
	 */
	public void setHideFormats( String formats )
	{
		if ( "all".equalsIgnoreCase( formats ) )
		{
			isAllHidden = true;
			hiddenFormatsString = "all";
			return;
		}
		hiddenFormats = parseHiddenFormats( formats );
		hiddenFormatsString = generateHiddenFormatsString( );
	}

	public void setIsGroupRoot( boolean isGroupRoot )
	{
		this.isGroupRoot = isGroupRoot;
	}
	
	public boolean isHidden( String format )
	{
		if ( format == null )
		{
			return false;
		}
		if ( isAllHidden )
		{
			return true;
		}
		if ( hiddenFormats == null )
		{
			return false;
		}
		return hiddenFormats.contains( format );
	}

	public boolean isBlank( )
	{
		return tocValue == null;
	}
	
	public Object getTOCValue( )
	{
		return tocValue;
	}

	public void setTOCValue( Object tocValue )
	{
		this.tocValue = tocValue;
	}

	public static TOCNode copyLocalizedNode( TOCTreeNode node, ULocale locale )
	{
		TOCNode copy = new TOCNode( node );
		if ( locale == null )
		{
			locale = ULocale.getDefault( );
		}
		copy.setDisplayString( localize( node.getTOCValue( ), locale ) );
		return copy;
	}
	
	public int hashCode( )
	{
		return nodeId == null ? 0 : nodeId.hashCode( );
	}
	
	private static String localize( Object value, ULocale locale )
	{
		if ( value == null )
		{
			return null;
		}
		String displayString = null;
		if (value instanceof Number)
		{
			NumberFormatter fmt = new NumberFormatter( locale );
			displayString = fmt.format( (Number) value );
		}
		else if ( value instanceof Date )
		{
			DateFormatter fmt = new DateFormatter( locale );
			displayString = fmt.format( (Date) value );
		}
		else if (value instanceof String)
		{
			displayString = (String)value;
		}
		else
		{
			displayString = value.toString();
		}
		return displayString;
	}

	private Set parseHiddenFormats( String formats )
	{
		if ( formats == null || formats.trim( ).length( ) == 0 )
		{
			return null;
		}
		String[] allFormats = formats.split( "," );
		Set hiddenFormats = new HashSet( allFormats.length );
		for ( int i = 0; i < allFormats.length; i++ )
		{
			String format = allFormats[i].trim( );
			hiddenFormats.add( format );
		}
		return hiddenFormats;
	}

	private String generateHiddenFormatsString(  )
	{
		if ( hiddenFormats == null )
		{
			return null;
		}
		StringBuffer formats = new StringBuffer( );
		Iterator iterator = hiddenFormats.iterator( );
		while( iterator.hasNext( ))
		{
			if ( formats.length( ) != 0 )
			{
				formats.append( ',' );
			}
			formats.append( iterator.next( ) );
		}
		return formats.toString( );
	}
}
