package controllers;

import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;

import play.Logger;
import play.data.Form;
import play.libs.Json;
import play.mvc.*;
import views.html.accountPage;
import models.*;
import play.data.Form;

@Security.Authenticated(Secured.class)
public class CtrlSource extends Controller {

	static private Form<Source> sourceForm = Form.form(Source.class);

	@Security.Authenticated(Secured.class)
	public static Result add() {
		Form<Source> theForm = sourceForm.bindFromRequest();
		if(theForm.hasErrors()) {
		  return badRequest("Bad request");
		} else {
		  Source submitted = theForm.get();
		  return redirect(routes.Application.manage());
		}
	}

	@Security.Authenticated(Secured.class)
	public static Result post(Long id) {
		User currentUser = Secured.getCurrentUser();
		return post(currentUser, id);
	}

	@Security.Authenticated(Secured.class)      
  public static Result edit() {
    return TODO; //ok(accountPage.render(getUser(), userForm));
  }
	
	@Security.Authenticated(Secured.class)      
  public static Result submit() {
		/* TODO:
		 * Create source from Form or update existing
		 * Create a parser from an embedded form and associate the parser with the new source
		*/
  	Form<Source> theForm = sourceForm.bindFromRequest();
    if(theForm.hasErrors()) {
      return badRequest("Bad request");
    } else {
  		User currentUser = Secured.getCurrentUser();
      Source submitted = theForm.get();
      try { Source.create(submitted); }
      catch (Exception e) { return badRequest("Bad request"); }
      return redirect(routes.CtrlSource.getById(submitted.id));
    }
  }
	
	public static Result postByUserKey(Long id, String ownerToken) {
		User owner = User.getByToken(ownerToken);
		return post(owner, id);
	}

	private static Result post(User user, Long id) {
		// rightnow only owner can post
		Source source = Source.get(id, user);
		return postBySource(source);
		// resolve device from device list
		// if public: good
		// if this currentUser.username is in ACL: good
		// else error message
	}

	public static Result postBySourceKey(Long id, String key) {
		Source source = Source.get(id, key);
		return postBySource(source);
	}

	private static Result postBySource(Source source) {
		if (source != null) {
			try {
				String strBody = request().body().asText();
				Logger.info("[Streams] post received from: " + " URI "
						+ request().uri() + ", content type: "
						+ request().getHeader("Content-Type") + ", payload: " + strBody);
				if (!source.parseAndPost(request())) {
					return badRequest("Bad request: Can't parse!");
				}
			} catch (Exception e) {
				Logger.info("[Streams] Exception " + e.getMessage());
//				Logger.info("[Streams] User null"
//						+ Boolean.toString(currentUser == null));
				return badRequest("Bad request: Error!");
			}
			return ok("ok");
		}
		return notFound();
	}

	@Security.Authenticated(Secured.class)
	public static Result getById(Long id) {
		User currentUser = Secured.getCurrentUser();
		Source source = Source.get(id, currentUser);
		return TODO;
	}

	public static Result getData(String ownerName, String path, Long tail,
			Long last, Long since) {
		final User user = Secured.getCurrentUser();
		final User owner = User.getByUserName(ownerName);
		// if(user == null) return notFound();
		return getData(user, owner, path, tail, last, since);
	}

	public static Result getDataById(Long id, Long tail, Long last, Long since) {
		final User user = Secured.getCurrentUser();
		// if(user == null) return notFound();
		Stream stream = Stream.get(id);
		if (stream == null) {
			return notFound();
		}
		return getData(user, stream, tail, last, since);
	}

	public static Result getDataByUserKey(String user_token, String path,
			Long tail, Long last, Long since) {
		final User user = Secured.getCurrentUser();
		final User owner = User.getByToken(user_token);
		// if(user == null) return notFound();
		return getData(user, owner, path, tail, last, since);
	}

	// @Security.Authenticated(Secured.class)
	private static Result getData(User currentUser, User owner, String path,
			Long tail, Long last, Long since) {
		Vfile f = FileSystem.readFile(owner, path);
		if (f == null) {
			return notFound();
		}
		Stream stream = f.getLink();
		if (stream == null) {
			return notFound();
		}
		return getData(currentUser, stream, tail, last, since);

	}

	private static Result getData(User currentUser, Stream stream, Long tail,
			Long last, Long since) {
		if (stream == null) {
			return notFound();
		}

		if (!stream.canRead(currentUser))
			return unauthorized("Private stream!");

		List<DataPoint> dataSet = null;
		if (tail < 0 && last < 0 && since < 0) {
			tail = 1L;
		}
		if (tail >= 0) {
			dataSet = stream.getDataPointsTail(tail);
		} else if (last >= 0) {
			dataSet = stream.getDataPointsLast(last);
		} else if (since >= 0) {
			dataSet = stream.getDataPointsSince(since);
		} else {
			throw new RuntimeException("This cannot happen!");
		}

		ObjectNode result = Json.newObject();
		ArrayNode time = result.putArray("time");
		ArrayNode data = result.putArray("data");

		for (DataPoint dataPoint : dataSet) {
			time.add(dataPoint.timestamp);
			if (stream.getType() == Stream.StreamType.DOUBLE) {
				data.add((Double) dataPoint.getData());
			}
		}

		return ok(result);
	}
}

@@ -808,16 +808,46 @@
 .get();%0A
+%09%09  Source.create(submitted);%0A
 %09%09  retu
@@ -1576,18 +1576,16 @@
  else %7B%0A
-  
 %09%09User c
@@ -1623,22 +1623,18 @@
 User();%0A
-      
+%09%09
 Source s
@@ -1659,22 +1659,18 @@
 .get();%0A
-      
+%09%09
 try %7B So
@@ -1695,22 +1695,18 @@
 ted); %7D%0A
-      
+%09%09
 catch (E
@@ -1755,22 +1755,18 @@
 st%22); %7D%0A
-      
+%09%09
 return r
@@ -1815,20 +1815,17 @@
 d.id));%0A
-    
+%09
 %7D%0A  %7D%0A%09%0A

save source