package org.netmelody.cieye.server.observation;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.netmelody.cieye.core.domain.Feature;
import org.netmelody.cieye.core.observation.CiSpy;
import org.netmelody.cieye.core.observation.CommunicationNetwork;
import org.netmelody.cieye.core.observation.KnownOffendersDirectory;
import org.netmelody.cieye.core.observation.ObservationAgency;
import org.netmelody.cieye.server.CiSpyAllocator;

public final class IntelligenceAgency implements CiSpyAllocator {

    private final Properties agencyConfiguration = new Properties();
    private final Map<String, CiSpy> witnesses = new HashMap<String, CiSpy>();
    
    private final CommunicationNetwork network;
    private final KnownOffendersDirectory directory;
    
    public IntelligenceAgency(CommunicationNetwork network, KnownOffendersDirectory directory) {
        this.network = network;
        this.directory = directory;
        try {
            agencyConfiguration.load(IntelligenceAgency.class.getResourceAsStream("CiObservationModules.properties"));
        } catch (IOException e) {
            throw new IllegalStateException("Failed to load CI Observation Modules");
        }
    }
    
    @Override
    public CiSpy spyFor(Feature feature) {
        if (!witnesses.containsKey(feature.endpoint())) {
            witnesses.put(feature.endpoint(), createSpyFor(feature));
        }
        return witnesses.get(feature.endpoint());
    }

    private CiSpy createSpyFor(Feature feature) {
        final String featureTypeName = feature.type().name();
        if (!agencyConfiguration.containsKey(featureTypeName)) {
            throw new IllegalStateException("No CI Observation Module for " + featureTypeName);
        }
        
        try {
            @SuppressWarnings("unchecked")
            final Class<? extends ObservationAgency> agencyClass =
                 (Class<? extends ObservationAgency>) Class.forName(agencyConfiguration.getProperty(featureTypeName));
            return new PollingSpy(agencyClass.newInstance().provideSpyFor(feature, network, directory));
        } catch (Exception e) {
            throw new IllegalStateException("Failed to load CI Observation Module for " + featureTypeName, e);
        }
    }
}

@@ -74,34 +74,8 @@
 on;%0A
-import java.util.HashMap;%0A
 impo
@@ -92,16 +92,16 @@
 il.Map;%0A
+
 import j
@@ -470,16 +470,100 @@
 cator;%0A%0A
+import com.google.common.base.Function;%0Aimport com.google.common.collect.MapMaker;%0A%0A
 public f
@@ -708,30 +708,31 @@
 e final Map%3C
-String
+Feature
 , CiSpy%3E wit
@@ -748,31 +748,190 @@
 new 
-HashMap%3CString, CiSpy%3E(
+MapMaker().makeComputingMap(new Function%3CFeature, CiSpy%3E() %7B%0A        @Override%0A        public CiSpy apply(Feature feature) %7B%0A            return createSpyFor(feature);%0A        %7D%0A    %7D
 );%0A 
@@ -1540,146 +1540,8 @@
 ) %7B%0A
-        if (!witnesses.containsKey(feature.endpoint())) %7B%0A            witnesses.put(feature.endpoint(), createSpyFor(feature));%0A        %7D%0A
     
@@ -1576,19 +1576,8 @@
 ture
-.endpoint()
 );%0A 

use MapMaker