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 static 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
            return;
        } 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();
    }
}
