/*
 * Activation.java
 * Created on May 18, 2005 
 * Author: 	L�szl� Felf�ldi, Etixpert GmbH
 * mail:	laszlo.felfoldi@etixpert.com		
 */
package com.etixpert.evolution.app.bonus.handler;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.jdom2.Element;

import com.etixpert.evolution.app.bonus.BonusData;
import com.etixpert.evolution.app.bonus.Handler;
import com.etixpert.evolution.event.Event;
import com.etixpert.evolution.value.DistributorValue;
import com.etixpert.evolution.value.bonus.BonusDefinitionValue;

public class Activation implements Handler {
	private Set subject;
	private Map values;
	boolean rollUp = false;
	
	public Activation(BonusDefinitionValue src) {
		subject = new HashSet();
		values  = new Hashtable();
		
		// Format with rollup: bonus1,bonus2,...:R?level1:metrics1=limit11,metrics2=limit12,...;level2:metrics1=...
		// Format without rollup: bonus1,bonus2,...?level1:metrics1=limit11,metrics2=limit12,...;level2:metrics1=...
		String[] main = src.getData().split("\\?");
	
		String[] opts = main[0].split(":");
		rollUp = opts.length > 1 && opts[1].equals("R");
		
		String[] subjects = opts[0].split(",");
		for (int i = 0; i < subjects.length; i++) {
			subject.add(subjects[i]);
		}
		
		String[] rowitems = main[1].split(";");
		for (int i = 0; i < rowitems.length; i++) {
			String[] name_sect = rowitems[i].split(":");
			Map entries = new Hashtable();
			values.put(BonusDefinitionValue.getLevel(name_sect[0]), entries);
			if (name_sect.length > 1) {
				String[] items = name_sect[1].split(",");
				for (int j = 0; j < items.length; j++) {
					String[] name_val = items[j].split("=");
					entries.put(name_val[0], new Double(name_val[1]));
				}
			}
		}
	}

	private double inactivateSpecialBonus(BonusData bd, String key) {
		if (!subject.contains(key)) return 0;
		
		double specbonus = bd.getSpecialBonusValue(key);
		if (specbonus != 0) {;
			String name = bd.getSpecialBonusName(key);
			// inactive already
			if (name.startsWith("!")) return 0;
			
			bd.setSpecialBonus(key, "!" + name, specbonus);
		}
		return specbonus;
	}
	
	/* (non-Javadoc)
	 * @see com.etixpert.evolution.app.bonus.Handler#handle(com.etixpert.evolution.event.Event)
	 */
	public boolean handle(Event event, Map environment) {
		Set notActives = new HashSet();
		
		// set the activation state
		for (Iterator it = environment.values().iterator(); it.hasNext(); ) {
			DistributorValue dv = (DistributorValue) it.next();
			BonusData bd = dv.getActBonus();
			
			if (dv.getLevelId() == null || bd == null) continue;
		
			Map row = (Map) values.get(dv.getLevelId());
			if (row == null) {
				row = (Map) values.get("");
			}
			if (row != null) {
				boolean active = true;
				Double limit = null;
				if ((limit = (Double) row.get("PV"))  != null) active &= bd.getpPV()  >= limit.doubleValue();
				if ((limit = (Double) row.get("EV"))  != null) active &= bd.getpEV()  >= limit.doubleValue();
				if ((limit = (Double) row.get("PEV")) != null) active &= bd.getpPEV() >= limit.doubleValue();
				if ((limit = (Double) row.get("TV"))  != null) active &= bd.getpTV()  >= limit.doubleValue();
				if ((limit = (Double) row.get("OV"))  != null) active &= bd.getpOV()  >= limit.doubleValue();
				
				if (!active) notActives.add(dv);
			}
		}
		
		// rolling up values
		for (Iterator it = environment.keySet().iterator(); it.hasNext(); ) {
			DistributorValue dv = (DistributorValue) environment.get(it.next());
			if (notActives.contains(dv)) {
				BonusData bd = dv.getActBonus();
				
				System.err.println(bd.getDistributor().getId() + " not active");
				for (BonusData bd2 = bd; bd2 != null; bd2 = bd2.getPrev()) {
					double bonus = 0;
					if (subject.contains("PB" )) {bonus += bd2.getPersonalBonus()    ; bd2.setPersonalBonus    (-bd2.getPersonalBonus());}
					if (subject.contains("DB" )) {bonus += bd2.getDifferentialBonus(); bd2.setDifferentialBonus(-bd2.getDifferentialBonus());}
					if (subject.contains("MB" )) {bonus += bd2.getManagerBonus()     ; bd2.setManagerBonus     (-bd2.getManagerBonus());}
					if (subject.contains("MBC")) {bd2.setManagerBonusCompressed(true);}
					if (subject.contains("TB" )) {bonus += bd2.getTradeMarginBonus() ; bd2.setTradeMarginBonus (-bd2.getTradeMarginBonus());}
					
					if (subject.contains("CB" )) bonus += inactivateSpecialBonus(bd2, "CB");
					if (subject.contains("WPB")) bonus += inactivateSpecialBonus(bd2, "WPB");
				
					if (rollUp) {
						BonusData bd3 = bd2;
						while ((bd3 = bd3.getSponsorData()) != null) {
							if (!notActives.contains(bd3.getDistributor())) break;
						}
						
						if (bd3 != null) {
							System.err.println("rolling up " + bonus + " to " + bd3.getDistributor().getId());
							if (bonus > 0) bd3.addToSpecialBonus(this, "Rollup", bonus);										
						}
					}
				}
			} 
		}
		return true;
	}
	
	public void toXML(Element to) {
	}
}
