/*
 * BonusDetails.java
 * Created on Apr 30, 2005 
 * Author: 	L�szl� Felf�ldi, Etixpert GmbH
 * mail:	laszlo.felfoldi@etixpert.com		
 */
package com.etixpert.evolution.value.bonus;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.jdom2.Document;
import org.jdom2.Element;

import com.etixpert.evolution.app.bonus.Engine;
import com.etixpert.evolution.event.Event;
import com.etixpert.evolution.value.Value;

public class BonusDefinitionValue extends Value {
	private Object eventId;
	private Object levelId;
	private Object distributorId;
	private Date fromDate;
	private Date toDate;
	public int priority;
	private String className;
	private String condition;
	private String data;

	private static Map items  = new Hashtable();
	private static Map levels = new Hashtable();
	
	
	public static class PriorityComparator implements Comparator {
		public int compare(Object o1, Object o2) {
			int p1 = ((BonusDefinitionValue) o1).priority;
			int p2 = ((BonusDefinitionValue) o2).priority;
			return p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
		}
	}
	
	public BonusDefinitionValue(Object aEventId, Object aLevelId, Object aDistributorId, Date aFromDate, Date aToDate, String aCondition, int aPritority, String aClassName, String aData){
		eventId = aEventId;
		levelId = aLevelId;
		distributorId = aDistributorId;
		fromDate = aFromDate;
		toDate = aToDate;
		condition = aCondition;
		priority = aPritority;
		className = aClassName;
		data = aData;
	}
	
	public Object getBonusId() {
		int d = hashCode();
		return new Integer(hashCode());
		/* 
		 * TODO ID should be from the database
		 */ 
	}
	
	public Object getDistributorId() {
		return distributorId;
	}
	
	public String getClassName() {
		return className;
	}
	
	public String getData() {
		return data;
	}
	
	public Object getLevelId() {
		return levelId;
	}
	
	public Date getFromDate() {
		return fromDate;
	}
	
	public Date getToDate() {
		return toDate;
	}
	
	public String getCondition() {
		return condition;
	}
	
	private static DateFormat dateformat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, Locale.GERMAN);		

	private static void findByDate(Set target, Set data, Event event) {
		if (data != null) {
			for (Iterator it = data.iterator(); it.hasNext(); ) {
				BonusDefinitionValue item = (BonusDefinitionValue) it.next();
				if (!event.getEventDate().before(item.getFromDate()) &&
						!event.getEventDate().after(item.getToDate())) {
					target.add(item);
				}	
			}
		}
	}
	
	private static void findByDistributor(Set target, Map data, Event event) {
		if (data != null) {
			BonusDefinitionValue val = null;
			Object eventTargetId = event.getEventTarget().getId();
			if (eventTargetId != null) {
				findByDate(target, (Set) data.get(eventTargetId), event);				
			}
			findByDate(target, (Set) data.get(""), event);
		}
	}
	
	private static void findByLevelId(Set target, Map data, Event event) {
		if (data != null) {
			Object eventTargetLevelId = event.getEventTargetLevelId();
			if (eventTargetLevelId != null) {
				findByDistributor(target, (Map) data.get(eventTargetLevelId), event);
			}
			findByDistributor(target, (Map) data.get(""), event);
		}
	}
	
	public static Set findByEvent(Event event) {
		Set ret = new TreeSet(new BonusDefinitionValue.PriorityComparator());
		findByLevelId(ret, (Map) items.get(event.getEventId()), event);
		return ret;
	}
	
	private static void setByDistributorId(Map src, Object key, BonusDefinitionValue bd) {
		Set list = (Set) src.get(key);
		if (list == null) {
			src.put(key, list = new HashSet());
		}
		list.add(bd);
	}
	
	private static void setByLevelId(Map src, Object key, BonusDefinitionValue bd) {
		Map map = (Map) src.get(key);
		if (map == null) {
			src.put(key, map = new Hashtable());
		}
		setByDistributorId(map, bd.getDistributorId(), bd);
//		setByDistributorId(map, "", bd);
	}
	
	private static void setByEventId(Object key, BonusDefinitionValue bd) {
		Map map = (Map) items.get(key);
		if (map == null) {
			items.put(key, map = new Hashtable());
		}
		setByLevelId(map, bd.getLevelId(), bd);
//		setByLevelId(map, "", bd);
	}
	
	public static Object getLevel(Object id) {
		return levels.containsKey(id) ? levels.get(id) : id; 
	}
	
	public static Object getLevelInt(String id) {
		Object ret = id;
		try { ret = new Integer(id); } catch (Exception e) {}
		return ret;
	}
	
	
	public static void fromXML(Document doc) throws ParseException {
		items.clear();
		levels.clear();
		Engine.resetHandlerCache();
		Element levelItems = doc.getRootElement().getChild("levels");
		if (levelItems != null) {
			List items = levelItems.getChildren();
			for (Iterator it  = items.iterator(); it.hasNext(); ) {
				Element e = (Element) it.next();
				levels.put(e.getAttributeValue("Id"), new Integer(e.getAttributeValue("Val")));
			}
		}
		
		List items = doc.getRootElement().getChildren("handler");
		for (Iterator it = items.iterator(); it.hasNext(); ) {
			Element e = (Element) it.next();
			Integer eventId = new Integer(e.getAttributeValue("EventId"));
			Object levelId = e.getAttributeValue("LevelId");
			Object distributorId = e.getAttributeValue("DistributorId");
			BonusDefinitionValue bd = new BonusDefinitionValue(
										eventId, levelId, distributorId,
										dateformat.parse(e.getAttributeValue("From")),
										dateformat.parse(e.getAttributeValue("To")),
										e.getAttributeValue("Condition"),
										Integer.parseInt(e.getAttributeValue("Priority")),
										e.getAttributeValue("ClassName"),
										e.getAttributeValue("Data"));
			
			setByEventId(eventId, bd);
		}
	}
}
