package net.onrc.onos.core.intent;

import java.util.Collection;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;

import net.onrc.onos.core.intent.Intent.IntentState;
import net.onrc.onos.core.intent.runtime.IntentStateList;

/**
 * @author Toshio Koide (t-koide@onlab.us)
 */
public class IntentMap {
	private HashSet<ChangedListener> listeners = new HashSet<>();
	private HashMap<String, Intent> intents = new HashMap<>();
	private	LinkedList<ChangedEvent> events = new LinkedList<>();

	public enum ChangedEventType {
		/**
		 * Added new intent.
		 */
		ADDED,

		/**
		 * Removed existing intent.
		 * The specified intent is an instance of Intent class (not a child class)
		 * Only id and state are valid.
		 */
		REMOVED,

		/**
		 * Changed state of existing intent.
		 * The specified intent is an instance of Intent class (not a child class)
		 * Only id and state are valid.
		 */
		STATE_CHANGED,
	}

	public class ChangedEvent {
		public ChangedEvent(ChangedEventType eventType, Intent intent) {
			this.eventType = eventType;
			this.intent = intent;
		}
		public ChangedEventType eventType;
		public Intent intent;
	}

	public interface ChangedListener extends EventListener {
		void intentsChange(LinkedList<ChangedEvent> events);
	}

	//================================================================================
	// public methods
	//================================================================================

	public void executeOperations(IntentOperationList operations) {
		for (IntentOperation operation: operations) {
			switch (operation.operator) {
			case ADD:
				handleAddOperation(operation);
				break;
			case REMOVE:
				handleRemoveOperation(operation);
				break;
			case ERROR:
				handleErrorOperation(operation);
				break;
			}
		}
		notifyEvents();
	}

	public void purge() {
		LinkedList<String> removeIds = new LinkedList<>();
		for (Entry<String, Intent> entry: intents.entrySet()) {
			Intent intent = entry.getValue();
			if (intent.getState() == IntentState.DEL_ACK
					|| intent.getState() == IntentState.INST_NACK) {
				removeIds.add(intent.getId());
			}
		}
		for (String intentId: removeIds) {
			removeIntent(intentId);
		}
		notifyEvents();
	}

	public void changeStates(IntentStateList states) {
		for (Entry<String, IntentState> state: states.entrySet()) {
			setState(state.getKey(), state.getValue());
		}
		notifyEvents();
	}

	public Intent getIntent(String intentId) {
		return intents.get(intentId);
	}

	public Collection<Intent> getAllIntents() {
		return intents.values();
	}

	public void addChangeListener(ChangedListener listener) {
		listeners.add(listener);
	}

	public void removeChangedListener(ChangedListener listener) {
		listeners.remove(listener);
	}

	//================================================================================
	// methods that affect intents map (protected)
	//================================================================================

	protected void putIntent(Intent intent) {
		if (intents.containsKey(intent.getId()))
			removeIntent(intent.getId());
		intents.put(intent.getId(), intent);
		events.add(new ChangedEvent(ChangedEventType.ADDED, intent));
	}

	protected void removeIntent(String intentId) {
		Intent intent = intents.remove(intentId);
		if (intent == null) return;
		events.add(new ChangedEvent(ChangedEventType.REMOVED, intent));
	}

	protected void setState(String intentId, IntentState state) {
		Intent intent = intents.get(intentId);
		if (intent == null) return;
		intent.setState(state);
		events.add(new ChangedEvent(ChangedEventType.STATE_CHANGED, intent));
	}

	//================================================================================
	// helper methods (protected)
	//================================================================================

	protected void handleAddOperation(IntentOperation operation) {
		putIntent(operation.intent);
	}

	protected void handleRemoveOperation(IntentOperation operation) {
		Intent intent = getIntent(operation.intent.getId());
		if (intent == null) {
			// TODO error handling
		}
		else {
			setState(intent.getId(), IntentState.DEL_REQ);
		}
	}

	protected void handleErrorOperation(IntentOperation operation) {
		//TODO put error message into the intent

		ErrorIntent errorIntent = (ErrorIntent) operation.intent;
		Intent targetIntent = intents.get(errorIntent.getId());
		if (targetIntent == null) {
			// TODO error handling
			return;
		}

		switch (targetIntent.getState()) {
		case CREATED:
		case INST_REQ:
		case INST_ACK:
		case REROUTE_REQ:
			setState(targetIntent.getId(), IntentState.INST_NACK);
			break;
		case DEL_REQ:
			setState(targetIntent.getId(), IntentState.DEL_PENDING);
			break;
		case INST_NACK:
		case DEL_PENDING:
		case DEL_ACK:
			// do nothing
			break;
		}
	}

	protected void notifyEvents() {
		for (ChangedListener listener: listeners) {
			listener.intentsChange(events);
		}
		events.clear();
	}
}
