package controllers;

import java.io.IOException;
import java.util.Collection;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;

import controllers.api.JsonManager;
import models.Deployment;
import models.FeedCollection;
import models.FeedSource;
import models.FeedVersion;
import models.JsonViews;
import models.Note;
import models.User;
import play.mvc.BodyParser;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Security;

/**
 * Handle database dump/reload.
 * @author mattwigway
 *
 */
public class Dump extends Controller {
    /**
     * Represents a snapshot of the database. This require loading the entire database into RAM.
     * This shouldn't be an issue, though, as the feeds are stored separately. This is only metadata.
     */
    public static class DatabaseState {
        public Collection<FeedCollection> feedCollections;
        public Collection<FeedSource> feedSources;
        public Collection<FeedVersion> feedVersions;
        public Collection<Note> notes;
        public Collection<User> users;
        public Collection<Deployment> deployments;
    }
    
    private static JsonManager<DatabaseState> json =
            new JsonManager<DatabaseState>(DatabaseState.class, JsonViews.DataDump.class);
    
    @Security.Authenticated(Admin.class)
    public static Result dump () throws JsonProcessingException {
        DatabaseState db = new DatabaseState();
        db.feedCollections = FeedCollection.getAll();
        db.feedSources = FeedSource.getAll();
        db.feedVersions = FeedVersion.getAll();
        db.notes = Note.getAll();
        db.users = User.getAll();
        db.deployments = Deployment.getAll();
        
        return ok(json.write(db)).as("application/json");
    }
    
    // this is not authenticated, because it has to happen with a bare database (i.e. no users)
    // this method in particular is coded to allow up to 100MB of data to be posted
    @BodyParser.Of(value=BodyParser.Json.class, maxLength = 100 * 1024 * 1024)
    public static Result load () throws JsonParseException, JsonMappingException, IOException {
        // TODO: really ought to check all tables
        if (User.usersExist())
            return badRequest("database not empty");

        DatabaseState db = json.read(request().body().asJson());
        
        for (FeedCollection c : db.feedCollections) {
            c.save(false);
        }
        FeedCollection.commit();
        
        for (FeedSource s : db.feedSources) {
            s.save(false);
        }
        FeedSource.commit();
        
        for (FeedVersion v : db.feedVersions) {
            v.save(false);
        }
        FeedVersion.commit();
        
        for (Note n : db.notes) {
            n.save(false);
        }
        Note.commit();
        
        for (User u : db.users) {
            u.save(false);
        }
        User.commit();
        
        for (Deployment d : db.deployments) {
            d.save(false);
        }
        Deployment.commit();
        
        return ok("done");
    }
    
}

@@ -19,66 +19,8 @@
 s;%0A%0A
-import java.io.IOException;%0Aimport java.util.Collection;%0A%0A
 impo
@@ -201,256 +201,50 @@
 t co
-m.fasterxml.jackson.databind.JsonNode;%0A%0Aimport controllers.api.JsonManager;%0Aimport models.Deployment;%0Aimport models.FeedCollection;%0Aimport models.FeedSource;%0Aimport models.FeedVersion;%0Aimport models.JsonViews;%0Aimport models.Note;%0Aimport models.User
+ntrollers.api.JsonManager;%0Aimport models.*
 ;%0Aim
@@ -348,16 +348,74 @@
 urity;%0A%0A
+import java.io.IOException;%0Aimport java.util.Collection;%0A%0A
 /**%0A * H
@@ -1865,17 +1865,17 @@
 w up to 
-1
+5
 00MB of 
@@ -1952,17 +1952,17 @@
 ength = 
-1
+5
 00 * 102

increase max json upload size.