package com.github.grundlefleck.cieye;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;

import org.netmelody.cieye.core.domain.CiServerType;
import org.netmelody.cieye.core.domain.Feature;
import org.netmelody.cieye.core.domain.Status;
import org.netmelody.cieye.core.domain.TargetDetail;
import org.netmelody.cieye.core.domain.TargetDigest;
import org.netmelody.cieye.core.domain.TargetDigestGroup;
import org.netmelody.cieye.core.domain.TargetId;
import org.netmelody.cieye.core.logging.LogKeeper;
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 com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.io.Files;

public class MyPluginObservationAgency implements ObservationAgency {

	@Override
	public boolean canProvideSpyFor(CiServerType type) {
		return "PLUGIN_DEMO".equals(type.name());
	}

	@Override
	public CiSpy provideSpyFor(Feature feature, CommunicationNetwork network, KnownOffendersDirectory directory) {
		return new PluginDemoSpy();
	}

	static class PluginDemoSpy implements CiSpy {
		
		private final Map<TargetId, MonitoredFile> monitoredFiles = Maps.newHashMap();

		@Override
		public TargetDigestGroup targetsConstituting(Feature feature) {
			TargetDigest target = new TargetDigest(feature.name(), feature.endpoint(), feature.name(), Status.UNKNOWN);
			monitoredFiles.put(target.id(), new MonitoredFile(feature));
			return new TargetDigestGroup(Collections.singleton(target));
		}

		@Override
		public TargetDetail statusOf(TargetId target) {
			final MonitoredFile monitoredFile = monitoredFiles.get(target);
	        if (null == monitoredFile) {
	            return null;
	        }
			return detailsOf(target, monitoredFile);
		}

		@Override
		public boolean takeNoteOf(TargetId target, String note) {
			final MonitoredFile monitoredFile = monitoredFiles.get(target);
	        if (null == monitoredFile) {
	            return false;
	        }
	        monitoredFile.addNote(note);
	        return true;
		}
		
		public TargetDetail detailsOf(TargetId target, MonitoredFile monitoredFile) {
			String webUrl = "www.example.com";
			return new TargetDetail(target.id(), webUrl, monitoredFile.name, monitoredFile.status(), monitoredFile.timestamp());
		}
	}
	
	static class MonitoredFile {
		private static final Map<String, Status> internalToCiEye = ImmutableMap.of(
				"All Good", Status.GREEN, 
				"Uh-oh", Status.BROKEN,
				"Checking", Status.UNDER_INVESTIGATION);
		
		private final File file;
		private final String name;

		public MonitoredFile(Feature feature) {
			this.name = feature.name();
			this.file = new File(feature.endpoint(), feature.name());
		}
		
		public Status status() {
			try {
				String status = Files.readFirstLine(file, Charsets.UTF_8);
				return internalToCiEye.get(status);
			} catch (IOException e) {
				LogKeeper.logbookFor(getClass()).error("Couldn't find status", e);
				return Status.UNKNOWN;
			}
		}
		
		public long timestamp() {
			return file.lastModified();
		}
		
		public void addNote(String note) {
			try {
				String withNote = String.format("%s%n%s%n", "Checking", note);
				Files.write(withNote, file, Charsets.UTF_8);
			} catch (IOException e) {
				LogKeeper.logbookFor(getClass()).error("Couldn't add note", e);
			}
		}
	}
	

	public static void main(String[] args) {
		ObservationAgency agency = new MyPluginObservationAgency();
		
		agency.canProvideSpyFor(new CiServerType("PLUGIN_DEMO"));
	}

}

@@ -33,16 +33,91 @@
 cieye;%0A%0A
+import static org.netmelody.cieye.core.domain.Status.UNDER_INVESTIGATION;%0A%0A
 import j
@@ -129,16 +129,16 @@
 o.File;%0A
-
 import j
@@ -912,16 +912,105 @@
 arsets;%0A
+import com.google.common.collect.BiMap;%0Aimport com.google.common.collect.ImmutableBiMap;%0A
 import c
@@ -2749,24 +2749,26 @@
 tatic final 
+Bi
 Map%3CString, 
@@ -2802,16 +2802,18 @@
 mmutable
+Bi
 Map.of(%0A
@@ -3555,26 +3555,66 @@
 n%25s%25n%22, 
-%22Checking%22
+internalToCiEye.inverse().get(UNDER_INVESTIGATION)
 , note);
@@ -3769,187 +3769,14 @@
 %09%09%7D%0A
+
 %09%09%7D%0A%09%7D
-%0A%09%0A%0A%09public static void main(String%5B%5D args) %7B%0A%09%09ObservationAgency agency = new MyPluginObservationAgency();%0A%09%09%0A%09%09agency.canProvideSpyFor(new CiServerType(%22PLUGIN_DEMO%22));%0A%09%7D
 %0A%0A%7D%0A

Remove unused main method, use a bimap to support status mapping in both directions.