/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. and others.
 *
 * 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:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.css2.list;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jst.pagedesigner.css2.ICSSStyle;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyMeta;

/**
 * The counter is used to generate automatic conters and numbering for list
 * item. XXX: what do we deal with psedo? and we need to refer to web tools
 * content to consult for style content.
 * 
 * @author mengbo
 */
public class CounterValueGenerator implements ICounterValueGenerator {
	private final static int DEFAULT_INITIAL_VALUE = 0;

	private static final Set STRING_TYPES = new HashSet();

	static final Set NON_STRING_TYPES = new HashSet();
	static {
		NON_STRING_TYPES.add("disc"); //$NON-NLS-1$
		NON_STRING_TYPES.add("circle"); //$NON-NLS-1$
		NON_STRING_TYPES.add("square"); //$NON-NLS-1$
		STRING_TYPES.add("decimal"); //$NON-NLS-1$
		STRING_TYPES.add("decimal-leading-zero"); //$NON-NLS-1$
		STRING_TYPES.add("lower-roman"); //$NON-NLS-1$
		STRING_TYPES.add("upper-roman"); //$NON-NLS-1$
		STRING_TYPES.add("lower-greek"); //$NON-NLS-1$
		STRING_TYPES.add("lower-alpha"); //$NON-NLS-1$
		STRING_TYPES.add("lower-latin"); //$NON-NLS-1$
		STRING_TYPES.add("upper-alpha"); //$NON-NLS-1$
		STRING_TYPES.add("upper-latin"); //$NON-NLS-1$
		STRING_TYPES.add("hebrew"); //$NON-NLS-1$
		STRING_TYPES.add("armenian"); //$NON-NLS-1$
		STRING_TYPES.add("georgian"); //$NON-NLS-1$
		STRING_TYPES.add("cjk-ideographic"); //$NON-NLS-1$
		STRING_TYPES.add("hiragana"); //$NON-NLS-1$
		STRING_TYPES.add("katakana"); //$NON-NLS-1$
		STRING_TYPES.add("hiragana-iroha"); //$NON-NLS-1$
		STRING_TYPES.add("katakana-iroha"); //$NON-NLS-1$
	}

	private final static int DEFAULT_INCREMENT = 1;

	private boolean _first = true;

	private Integer _initial;

	private List _visitors;

	private int _count;

	private String _identifier;

	private String _styleType;

	private String _seperator;

	private ICSSStyle _style;

	/**
	 * @param identifier
	 * @param styleType
	 * @param seperator
	 * @param style
	 */
	public CounterValueGenerator(String identifier, String styleType,
			String seperator, ICSSStyle style) {
		_identifier = identifier;
		_styleType = styleType;
		_seperator = seperator;
		_style = style;
		if (HTMLListInfoHelper.getStartInt(style) != null) {
			_count = HTMLListInfoHelper.getStartInt(style).intValue();
		} else {
			_count = DEFAULT_INITIAL_VALUE;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.w3c.dom.css.Counter#getIdentifier()
	 */
	public String getIdentifier() {
		return _identifier;
	}

	/**
	 * @return the style  type 
	 * @see org.w3c.dom.css.Counter#getListStyle()
	 */
	public String getListStyle() {
		return _styleType;
	}

	/**
	 * @return the separator
	 * 
	 * @see org.w3c.dom.css.Counter#getSeparator()
	 */
	public String getSeparator() {
		return _seperator;
	}

	// /**
	// * @return Returns the type.
	// */
	// public String getType()
	// {
	// return _styleType;
	// }

	// /**
	// * @return Returns the markerString.
	// */
	// public String getTextValue()
	// {
	// Assert.isTrue(this.isText());
	// _index = getDeclaredIndex();
	// Node container = findParentComtainer();
	// if (container == null)
	// {
	// // what condition?
	// return "";
	// }
	// String exp = "";
	// int startIndex = getStartIndex(container);
	// int maxLength = calculateMaxlength(container, 0) + startIndex - 1;
	// Assert.isTrue(maxLength > 0);
	// if (_index == -1)
	// {
	// // no declared value
	// calculateIndex(container);
	// Assert.isTrue(_index > -1);
	// exp = Integer.toString(_index + startIndex);
	// }
	// else
	// {
	// exp = Integer.toString(_index);
	// }
	// if (getType() == CounterHelper.LIST_T_DECIMAL)
	// {
	// exp = appendSuffix(exp, Integer.toString(maxLength).length() -
	// exp.length());
	// }
	// else if (getType() == CounterHelper.LIST_T_DECIMAL_LEADING_ZERO)
	// {
	// exp = addPrefix(exp, maxLength - exp.length());
	// }
	// return exp + ".";
	//
	// }

	// private String addPrefix(String exp, int length)
	// {
	// while (length > 0)
	// {
	// exp = "0" + exp;
	// length--;
	// }
	// return exp;
	// }
	//
	// private String appendSuffix(String exp, int length)
	// {
	// while (length > 0)
	// {
	// exp = exp + " ";
	// length--;
	// }
	// return exp;
	// }

	// private boolean calculateIndex(Node node)
	// {
	// if (node == _node)
	// {
	// _index++;
	// return true;
	// }
	// String name = node.getNodeName();
	// if (name != null && name.equalsIgnoreCase("li"))
	// {
	// _index++;
	// }
	// if (!node.hasChildNodes())
	// {
	// return false;
	// }
	// node = node.getFirstChild();
	// while (node != null)
	// {
	// name = node.getNodeName();
	// if (name != null && !(name.equalsIgnoreCase("ul") ||
	// name.equalsIgnoreCase("ol")))
	// {
	// if (calculateIndex(node))
	// {
	// return true;
	// }
	// }
	// node = node.getNextSibling();
	// }
	// return false;
	// }

	// This method may be refered for the zero-leading calculation.
	// private int calculateMaxlength(Node node, int index)
	// {
	// String name = node.getNodeName();
	// if (name != null && name.equalsIgnoreCase("li"))
	// {
	// index++;
	// }
	// if (!node.hasChildNodes())
	// {
	// return index;
	// }
	// node = node.getFirstChild();
	// while (node != null)
	// {
	// name = node.getNodeName();
	// if (name != null && !(name.equalsIgnoreCase("ul") ||
	// name.equalsIgnoreCase("ol")))
	// {
	// index = calculateMaxlength(node, index);
	// }
	// node = node.getNextSibling();
	// }
	// return index;
	// }
	//

	// private int getStartIndex(Node container)
	// {
	// String value = ((Element) container).getAttribute("start");
	// try
	// {
	// int index = Integer.parseInt(value);
	// if (index < 0)
	// {
	// return 1;
	// }
	// return index;
	// }
	// catch (Exception e)
	// {
	// return 1;
	// }
	// }

	// private boolean isStringTyped(ICSSStyle style)
	// {
	// style.getStyleProperty("list-style-type");
	// return true;
	// }

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#clone()
	 */
	protected Object clone() throws CloneNotSupportedException {
		CounterValueGenerator newInstance = new CounterValueGenerator(
				_identifier, _styleType, _seperator, _style);
		return newInstance;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.list.Counter2#increase()
	 */
	public void increase(int increment) {
		if (!_first || HTMLListInfoHelper.getStartInt(_style) == null) {
			_count += increment;
		}
		_first = false;
	}

	public void increase() {
		increase(DEFAULT_INCREMENT);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.list.Counter2#setCount()
	 */
	public ICounterValueGenerator resetCount() {
		try {
			ICounterValueGenerator counter = (ICounterValueGenerator) this
					.clone();
			_initial = null;
			_count = HTMLListInfoHelper.getStartInt(_style) != null ? HTMLListInfoHelper
					.getStartInt(_style).intValue()
					: DEFAULT_INITIAL_VALUE;
			return counter;
		} catch (CloneNotSupportedException e) {
			return null;
		}
	}

	/**
	 * @return Returns the _initial.
	 */
	public int getInitial() {
		if (HTMLListInfoHelper.getStartInt(_style) != null) {
			return HTMLListInfoHelper.getStartInt(_style).intValue();
		}
        return _initial != null ? _initial.intValue()
        		: DEFAULT_INITIAL_VALUE;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.list.Counter2#setCount()
	 */
	public ICounterValueGenerator resetCount(int initial) {
		try {
			CounterValueGenerator counter = (CounterValueGenerator) this
					.clone();
			_initial = new Integer(initial);
			_count = initial;
			return counter;
		} catch (CloneNotSupportedException e) {
			return null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.list.ICounterValueGenerator#setCount(org.eclipse.jst.pagedesigner.css2.list.HTMLListInfo)
	 */
	public void setCount(Integer value) {
		if (value != null) {
			_count = value.intValue();
			_first = false;
		}
	}

	// /**
	// * The clients of this counter need to regist them.
	// *
	// * @see
	// org.eclipse.jst.pagedesigner.css2.list.Counter2#regist(java.lang.Object)
	// */
	// public void regist(Object caller)
	// {
	// Assert.isTrue(caller instanceof ICSSStyle);
	// if (_visitors == null)
	// {
	// _visitors = new LinkedList();
	// }
	// if (!_visitors.contains(caller))
	// {
	// _visitors.add(caller);
	// }
	// }
	//
	// /**
	// * (non-Javadoc)
	// *
	// * @see
	// org.eclipse.jst.pagedesigner.css2.list.Counter2#unregist(java.lang.Object)
	// */
	// public void unregist(Object caller)
	// {
	// if (_visitors.contains(caller))
	// {
	// _visitors.remove(caller);
	// }
	// }

	/**
	 * Return the int value.
	 * 
	 * @author mengbo
	 */
	public int getCurrentCount() {
		return _count;
	}

	/**
	 * Currently we recalculate the count, to enhance the performance, we may
	 * use _count, but this requires delicate synchronization when the
	 * calculation is looped.
	 */
	public Integer getCount(Object oCaller) {
		Assert.isTrue(oCaller instanceof ICSSStyle && _visitors != null
				&& _visitors.size() > 0);
		ICSSStyle caller = (ICSSStyle) oCaller;
		if (!_visitors.contains(caller)) {
			return null;
		}
		int result = getInitial();

		for (int i = 0, n = _visitors.size(); i < n; i++) {
			ICSSStyle style = (ICSSStyle) _visitors.get(i);
			// get the count;
			Object counterIncrements = style
					.getStyleProperty(ICSSPropertyID.ATTR_COUNTER_INCREMENT);
			if (counterIncrements != null
					&& counterIncrements != ICSSPropertyMeta.NOT_SPECIFIED) {
				if (counterIncrements instanceof List) {
					List crList = (List) counterIncrements;
					for (int j = 0, nn = crList.size(); j < nn; j++) {
						IncrementObject rObject = (IncrementObject) crList
								.get(j);
						String name = rObject.getCounterName();
						if (getIdentifier().equalsIgnoreCase(name)) {
							if (rObject.getIncrement() != null) {
								result += rObject.getIncrement().intValue();
							} else {
								result += DEFAULT_INCREMENT;
							}
						}
					}
				}
			}
			if (style == caller) {
				return new Integer(result);
			}
		}
		return null;
	}
}
