package com.oguerreiro.resilient.activity;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ActivityRegistry {
	/* Activities by state */
	private final Map<String, List<String>> activitiesByState = new HashMap<String, List<String>>();
	private final Map<String, Activity> activitiesByKey = new HashMap<String, Activity>();
	
    @SuppressWarnings({ "unchecked", "rawtypes" })
	@Autowired
    public ActivityRegistry(List<Activity> activityList) {
    	for (Activity activity : activityList) {
    		if (activitiesByKey.containsKey(activity.getActivityKey())) {
    			throw new RuntimeException("Duplicated Activity key found : <" + activity.getActivityKey() + ">. Activity key must be unique.");
    		}
    		
    		activitiesByKey.put(activity.getActivityKey(), activity);
    		
			String className = activity.appliesToActivityDomainClass().getName();
			
			activity.appliesToStates().forEach((state) -> {
				String key = className + "@" + state;
				List<String> activitiesForState = activitiesByState.get(key);
				if (activitiesForState == null) {
					activitiesForState = new ArrayList<String>();
					activitiesByState.put(className + "@" + state , activitiesForState);
				}
				activitiesForState.add(activity.getActivityKey());
			});
			
		}
    }
    
    @SuppressWarnings("rawtypes")
	public Map<String, Activity> findActivitiesFor(String activityDomainClass, String currentState) {
    	String key = activityDomainClass + "@" + currentState;
    	List<String> activitiesForState = activitiesByState.get(key);
    	if (activitiesForState == null)
    		return Collections.emptyMap();
    	
    	Map<String, Activity> activities = new HashMap<String, Activity>();
    	for (String activityKey : activitiesForState) {
    		activities.put(activityKey, activitiesByKey.get(activityKey));
		}
    	return activities;
    }
    
    /**
     * Get {@link Activity} by the key, when it was registered
     * 
     * @param activityKey
     * @return
     */
    public Activity getActivity(String activityKey) {
    	Activity activity= activitiesByKey.get(activityKey);
    	
    	if (activity==null) {
    		// TODO : throw exception : ActivityNotFound for ActivityDomainClass and UUID
    	}
    	
    	return activitiesByKey.get(activityKey);
    }
    
    /**
     * Get {@link Activity} by the UUID, when it was registered. But also checks if it apoplies to the activityDomainClass.
     * 
     * @param activityUUID
     * @return
     */
    public Activity getActivity(String activityUUID, String activityDomainClass) {
    	Activity activity= this.getActivity(activityUUID);
    	
    	if (activity.appliesToActivityDomainClass().getName().equals(activityDomainClass)) {
    		return activity;
    	}
    	
    	//TODO : throw exception : ActivityNotFound for ActivityDomainClass and UUID
    	return null;
    }
}
