package org.sagebionetworks.bridge.sdk.integration;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.sagebionetworks.bridge.rest.model.Role.DEVELOPER;
import static org.sagebionetworks.bridge.rest.model.TemplateType.EMAIL_ACCOUNT_EXISTS;

import com.google.common.collect.ImmutableMap;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.sagebionetworks.bridge.rest.api.ForAdminsApi;
import org.sagebionetworks.bridge.rest.api.ForDevelopersApi;
import org.sagebionetworks.bridge.rest.exceptions.EntityNotFoundException;
import org.sagebionetworks.bridge.rest.model.Criteria;
import org.sagebionetworks.bridge.rest.model.GuidVersionHolder;
import org.sagebionetworks.bridge.rest.model.Template;
import org.sagebionetworks.bridge.rest.model.TemplateList;
import org.sagebionetworks.bridge.user.TestUserHelper;
import org.sagebionetworks.bridge.user.TestUserHelper.TestUser;

public class TemplateTest {
    
    TestUser admin;
    TestUser developer;
    Template template;
    
    @Before
    public void before() throws Exception {
        admin = TestUserHelper.getSignedInAdmin();
        developer = TestUserHelper.createAndSignInUser(TemplateTest.class, true, DEVELOPER);
    }
    
    @After
    public void after() throws Exception {
        // in case of earlier test failure, clean up
        if (template != null && template.getGuid() != null) {
            ForAdminsApi adminsApi = admin.getClient(ForAdminsApi.class);
            try {
                adminsApi.deleteTemplate(template.getGuid(), true).execute();    
            } catch(EntityNotFoundException e) {
                // this is okay
            }
        }
        developer.signOutAndDeleteUser();
    }
    
    @Test
    public void crudTemplate() throws Exception {
        Criteria criteria = new Criteria();
        criteria.setMinAppVersions(ImmutableMap.of("Android", 10));
        criteria.setMaxAppVersions(ImmutableMap.of("Android", 100));
        
        // create template
        template = new Template();
        template.setCriteria(criteria);
        template.setName("TestTemplate Name");
        template.setDescription("TestTemplate Description");
        template.setTemplateType(EMAIL_ACCOUNT_EXISTS);
        // These should be ignored
        template.setDeleted(true);
        
        ForDevelopersApi devsApi = developer.getClient(ForDevelopersApi.class);
        
        GuidVersionHolder keys = devsApi.createTemplate(template).execute().body();
        template.setGuid(keys.getGuid());
        template.setVersion(keys.getVersion());
        
        Template retrieved = devsApi.getTemplate(template.getGuid()).execute().body();
        assertEquals(template.getName(), retrieved.getName());
        assertEquals(template.getDescription(), retrieved.getDescription());
        assertEquals(EMAIL_ACCOUNT_EXISTS, retrieved.getTemplateType());
        assertFalse(retrieved.isDeleted());
        assertEquals(10, (int)retrieved.getCriteria().getMinAppVersions().get("Android"));
        assertEquals(100, (int)retrieved.getCriteria().getMaxAppVersions().get("Android"));
        
        // update template
        template.setName("TestTemplate Name Updated");
        template.setDescription("TestTemplate Description Updated");
        template.setDeleted(false);
        criteria.setMinAppVersions(ImmutableMap.of("Android", 11));
        criteria.setMaxAppVersions(ImmutableMap.of("Android", 99));
        
        keys = devsApi.updateTemplate(template.getGuid(), template).execute().body();
        template.setGuid(keys.getGuid());
        template.setVersion(keys.getVersion());
        
        retrieved = devsApi.getTemplate(template.getGuid()).execute().body();
        assertEquals(template.getName(), retrieved.getName());
        assertEquals(template.getDescription(), retrieved.getDescription());
        assertFalse(retrieved.isDeleted());
        assertEquals(11, (int)retrieved.getCriteria().getMinAppVersions().get("Android"));
        assertEquals(99, (int)retrieved.getCriteria().getMaxAppVersions().get("Android"));

        // logically delete template as an update, and through DELETE
        
        template.setDeleted(true);
        keys = devsApi.updateTemplate(template.getGuid(), template).execute().body();
        template.setGuid(keys.getGuid());
        template.setVersion(keys.getVersion());
        
        retrieved = devsApi.getTemplate(template.getGuid()).execute().body();
        assertTrue(retrieved.isDeleted());
        
        template.setDeleted(false);
        keys = devsApi.updateTemplate(template.getGuid(), template).execute().body();
        template.setGuid(keys.getGuid());
        template.setVersion(keys.getVersion());
        retrieved = devsApi.getTemplate(template.getGuid()).execute().body();
        assertFalse(retrieved.isDeleted());
        
        devsApi.deleteTemplate(template.getGuid(), false).execute();
        
        retrieved = devsApi.getTemplate(template.getGuid()).execute().body();
        assertTrue(retrieved.isDeleted());
        
        // get a page of templates with logical deletes
        TemplateList list = devsApi.getTemplates(EMAIL_ACCOUNT_EXISTS.name(), null, null, false).execute()
                .body();
        assertTrue(list.getItems().isEmpty());
        
        // get a page of templates without logical deletes
        list = devsApi.getTemplates(EMAIL_ACCOUNT_EXISTS.name(), null, null, true).execute().body();
        
        final String guid = keys.getGuid(); 
        if (!list.getItems().stream().anyMatch(template -> template.getGuid().equals(guid))) {
            fail("Should have found template");
        }
        
        // physically delete
        ForAdminsApi adminsApi = admin.getClient(ForAdminsApi.class);
        adminsApi.deleteTemplate(template.getGuid(), true).execute();        
        
        // it's really deleted
        try {
            devsApi.getTemplate(template.getGuid()).execute();
            fail("Should have thrown exception");
        } catch(EntityNotFoundException e) {

        }
    }

}

@@ -46,16 +46,66 @@
 ation;%0A%0A
+import static java.util.stream.Collectors.toList;%0A
 import s
@@ -421,16 +421,124 @@
 XISTS;%0A%0A
+import java.util.List;%0Aimport java.util.stream.Collectors;%0A%0Aimport com.google.common.collect.ImmutableList;%0A
 import c
@@ -2004,28 +2004,24 @@
 er();%0A    %7D%0A
-    
 %0A    @Test%0A 
@@ -5393,16 +5393,19 @@
 tes with
+out
  logical
@@ -5584,16 +5584,86 @@
 s().
-isEmpty(
+stream().noneMatch((template -%3E template.getGuid().equals(template.getGuid()))
 ));%0A
@@ -5702,35 +5702,32 @@
 f templates with
-out
  logical deletes
@@ -5840,67 +5840,19 @@
     
-%0A        final String guid = keys.getGuid(); %0A        if (!
+assertTrue(
 list
@@ -5881,16 +5881,17 @@
 nyMatch(
+(
 template
@@ -5924,75 +5924,31 @@
 als(
-guid))) %7B%0A            fail(%22Should have found template%22);%0A        %7D
+template.getGuid()))));
 %0A   

Check for guid in the list, rather than relying on only one template being present.