package com.simperium;

import com.simperium.client.Change;
import com.simperium.client.Bucket;
import com.simperium.client.Syncable;

import com.simperium.models.Note;

import com.simperium.test.MockBucket;

import junit.framework.TestCase;

import org.json.JSONObject;

public class ChangeTest extends TestCase {

    private Bucket<Note> mBucket;
    private Note mNote;

    protected void setUp()
    throws Exception {

        mBucket = MockBucket.buildBucket(new Note.Schema());

    }

    public void testModifyPayload()
    throws Exception {

        Note note = mBucket.newObject();
        note.setTitle("Hello world");

        Change change = new Change(Change.OPERATION_MODIFY, note);

        assertTrue(change.isModifyOperation());
        assertValidChangeObject(note, change);

        JSONObject diff = change.toJSONObject().getJSONObject("v");

        String expected = "{\"tags\":{\"v\":[],\"o\":\"+\"},\"deleted\":{\"v\":false,\"o\":\"+\"},\"title\":{\"v\":\"Hello world\",\"o\":\"+\"}}";
        assertEquals(expected, diff.toString());

    }

    public void testDeletePayload()
    throws Exception {

        Note note = mBucket.newObject();
        note.setTitle("Hello world");
        note.save();

        Change change = new Change(Change.OPERATION_REMOVE, note);

        assertTrue(change.isRemoveOperation());
        assertValidChangeObject(note, change);

    }

    public static void assertValidChangeObject(Syncable object, Change change)
    throws Exception {

        JSONObject changeJSON = change.toJSONObject();

        assertNotNull("Change missing ccid", changeJSON.optString("ccid"));
        assertNotNull("Change missing operation key `o`", changeJSON.optString("o"));
        assertEquals("Change id is incorrect", object.getSimperiumKey(), changeJSON.getString("id"));

        if (change.isRemoveOperation()) {
            assertFalse("Remove operation has a diff value", changeJSON.has("v"));
        } else {
            assertNotNull("Modify operation has no patch", changeJSON.optJSONObject("v"));
        }
    }

}
@@ -484,90 +484,18 @@
 ));%0A
-%0A
     
-%7D%0A%0A    public void testModifyPayload()%0A    throws Exception %7B%0A%0A        Note n
+    mN
 ote 
@@ -517,33 +517,34 @@
 ject();%0A        
-n
+mN
 ote.setTitle(%22He
@@ -553,24 +553,91 @@
 o world%22);%0A%0A
+    %7D%0A%0A    public void testModifyPayload()%0A    throws Exception %7B%0A%0A
         Chan
@@ -684,17 +684,18 @@
 MODIFY, 
-n
+mN
 ote);%0A%0A 
@@ -765,33 +765,34 @@
 lidChangeObject(
-n
+mN
 ote, change);%0A%0A 
@@ -1135,49 +1135,100 @@
     
+m
 Note
- note = mBucket.newObject(
+.save();%0A%0A        Change change = new Change(Change.OPERATION_REMOVE, mNote
 );%0A
+%0A
         
 note
@@ -1227,58 +1227,180 @@
     
-note.setTitle(%22Hello world%22
+assertTrue(change.isRemoveOperation());%0A        assertValidChangeObject(mNote, change
 );%0A
+%0A
     
+%7D%0A%0A
     
-note.save();
+public void testChangeWithFullObjectDataPaylaod()%0A    throws Exception %7B
 %0A%0A  
@@ -1453,32 +1453,32 @@
 ION_
-REMOVE, n
+MODIFY, mN
 ote);%0A
-%0A
         
 asse
@@ -1477,48 +1477,41 @@
     
-assertTrue(change.isRemoveOperation()
+change.setSendFullObject(true
 );%0A
+%0A
     
@@ -1538,17 +1538,18 @@
 eObject(
-n
+mN
 ote, cha
@@ -1546,32 +1546,143 @@
 mNote, change);%0A
+        assertEquals(mNote.getDiffableValue().toString(), change.toJSONObject().getJSONObject(%22d%22).toString());
 %0A    %7D%0A%0A    publ
@@ -2214,32 +2214,106 @@
 JSON.has(%22v%22));%0A
+            assertFalse(%22Remove operation has sv%22, changeJSON.has(%22sv%22));%0A
         %7D else %7B
@@ -2396,32 +2396,210 @@
 ONObject(%22v%22));%0A
+            if (object.getVersion() %3E 0) %7B%0A                assertEquals(%22Modify change did not have sv%22, (int) object.getVersion(), (int) changeJSON.getInt(%22sv%22));%0A            %7D%0A
         %7D%0A    %7D%0A

Test for presence of `d` and object data in change