package uk.gov.register.presentation.functional;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.common.collect.ImmutableList;
import io.dropwizard.jackson.Jackson;
import org.junit.Test;
import uk.gov.register.presentation.functional.testSupport.DBSupport;

import javax.ws.rs.core.Response;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;


public class RegisterResourceFunctionalTest extends FunctionalTestBase {

    @Test
    public void registerJsonShouldContainEntryView() throws Throwable {
        populateRegisterRegisterEntries();
        Response registerRegisterEntryResponse = getRequest("register", "/register/address.json");
        assertThat(registerRegisterEntryResponse.getStatus(), equalTo(200));

        cleanDatabaseRule.before();

        Long addressRegisterLastUpdatedTime = populateAddressRegisterEntries().get();
        Response addressRegisterResourceResponse = getRequest("address", "/register.json");
        assertThat(addressRegisterResourceResponse.getStatus(), equalTo(200));

        String addressRegisterResourceJsonResponse = addressRegisterResourceResponse.readEntity(String.class);
        assertThat(addressRegisterResourceJsonResponse, containsString("\"total-entries\":5"));
        assertThat(addressRegisterResourceJsonResponse, containsString("\"total-records\":3"));
        assertThat(addressRegisterResourceJsonResponse, containsString("\"total-items\":5"));
        assertThat(addressRegisterResourceJsonResponse, containsString(String.format("\"last-updated\":\"%s\"",
                Instant.ofEpochMilli(addressRegisterLastUpdatedTime).toString())));

        String registerRegisterEntryJsonResponse = registerRegisterEntryResponse.readEntity(String.class);
        assertThat(addressRegisterResourceJsonResponse, containsString(registerRegisterEntryJsonResponse));
    }

    public Optional<Long> populateAddressRegisterEntries() {
        return DBSupport.publishMessages(ImmutableList.of(
                "{\"hash\":\"hash1\",\"entry\":{\"name\":\"ellis\",\"address\":\"12345\"}}",
                "{\"hash\":\"hash2\",\"entry\":{\"name\":\"presley\",\"address\":\"6789\"}}",
                "{\"hash\":\"hash3\",\"entry\":{\"name\":\"ellis\",\"address\":\"145678\"}}",
                "{\"hash\":\"hash4\",\"entry\":{\"name\":\"updatedEllisName\",\"address\":\"145678\"}}",
                "{\"hash\":\"hash5\",\"entry\":{\"name\":\"ellis\",\"address\":\"6789\"}}"
        ));
    }

    public void populateRegisterRegisterEntries() throws IOException {
        InputStream registersStream = RegisterResourceFunctionalTest.class.getClassLoader().getResourceAsStream("config/registers.yaml");
        ObjectMapper yamlObjectMapper = Jackson.newObjectMapper(new YAMLFactory());
        ObjectMapper jsonObjectMapper = Jackson.newObjectMapper();

        List<Map<String, JsonNode>> registersYaml = yamlObjectMapper.readValue(registersStream, new TypeReference<List<Map<String, JsonNode>>>() {
        });

        SortedMap<Integer, String> registerEntries = registersYaml.stream().collect(Collectors.toMap(m -> m.get("serial-number").asInt(), m -> {
            try {
                return jsonObjectMapper.writeValueAsString(yamlObjectMapper.convertValue(m, ImportRegister.class));
            } catch (JsonProcessingException e) {
                throw new UncheckedIOException(e);
            }
        }, (a,b) -> a, TreeMap::new));

        DBSupport.publishMessages("register", registerEntries);
    }

    @JsonIgnoreProperties("serial-number")
    private static class ImportRegister {
        public String hash;
        public JsonNode entry;

        public ImportRegister() {}
    }
}

@@ -47,129 +47,8 @@
 l;%0A%0A
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;%0Aimport com.fasterxml.jackson.core.JsonProcessingException;%0A
 impo
@@ -197,16 +197,71 @@
 Mapper;%0A
+import com.fasterxml.jackson.databind.node.ObjectNode;%0A
 import c
@@ -585,45 +585,8 @@
 am;%0A
-import java.io.UncheckedIOException;%0A
 impo
@@ -3312,76 +3312,8 @@
 ));%0A
-        ObjectMapper jsonObjectMapper = Jackson.newObjectMapper();%0A%0A
     
@@ -3609,15 +3609,8 @@
 t(),
- m -%3E %7B
 %0A   
@@ -3618,19 +3618,24 @@
         
-try
+    m -%3E
  %7B%0A     
@@ -3649,206 +3649,232 @@
     
-return jsonObjectMapper.writeValueAsString(yamlObjectMapper.convertValue(m, ImportRegister.class));%0A            %7D catch (JsonProcessingException e) %7B%0A                throw new UncheckedIOException(e
+    ObjectNode rootNode = yamlObjectMapper.createObjectNode();%0A                    rootNode.set(%22hash%22, m.get(%22hash%22));%0A                    rootNode.set(%22entry%22, m.get(%22entry%22));%0A                    return rootNode.toString(
 );%0A 
@@ -3885,21 +3885,15 @@
     
-   %7D%0A
        
- 
 %7D, (
@@ -3993,194 +3993,7 @@
    %7D
-%0A%0A    @JsonIgnoreProperties(%22serial-number%22)%0A    private static class ImportRegister %7B%0A        public String hash;%0A        public JsonNode entry;%0A%0A        public ImportRegister() %7B%7D%0A    %7D
 %0A%7D%0A

Refactor insertion of registers.yaml into ordered_entry_index for Register register.