package uk.gov.register.resources;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.gov.register.core.Entry;
import uk.gov.register.core.Item;
import uk.gov.register.core.Register;
import uk.gov.register.core.RegisterContext;
import uk.gov.register.exceptions.SerializationFormatValidationException;
import uk.gov.register.exceptions.SerializedRegisterParseException;
import uk.gov.register.serialization.RSFFormatter;
import uk.gov.register.serialization.RSFResult;
import uk.gov.register.serialization.RegisterSerialisationFormat;
import uk.gov.register.service.RegisterSerialisationFormatService;
import uk.gov.register.util.ObjectReconstructor;
import uk.gov.register.views.representations.ExtraMediaType;

import javax.annotation.security.PermitAll;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicInteger;

@Path("/")
public class DataUpload {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final ObjectReconstructor objectReconstructor;
    private final RegisterSerialisationFormatService rsfService;
    private final RegisterContext registerContext;
    private final RSFFormatter rsfFormatter;

    @Inject
    public DataUpload(ObjectReconstructor objectReconstructor, RegisterSerialisationFormatService rsfService, RegisterContext registerContext) {
        this.objectReconstructor = objectReconstructor;
        this.rsfService = rsfService;
        this.registerContext = registerContext;
        this.rsfFormatter = new RSFFormatter();
    }

    @Context
    HttpServletRequest httpServletRequest;

    @POST
    @PermitAll
    @Path("/load")
    public void load(String payload) {
        try {
            Iterable<JsonNode> objects = objectReconstructor.reconstructWithCanonicalization(payload.split("\n"));
            mintItems(objects);
        } catch (Throwable t) {
            logger.error(Throwables.getStackTraceAsString(t));
            throw t;
        }
    }

    @POST
    @PermitAll
    @Consumes(ExtraMediaType.APPLICATION_RSF)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/load-rsf")
    public Response loadRsf(InputStream inputStream) {
        RSFResult loadResult;
        try {
            RegisterSerialisationFormat rsf = rsfService.readFrom(inputStream, rsfFormatter);
            loadResult = rsfService.processRegisterSerialisationFormat(rsf);
        } catch (SerializedRegisterParseException e) {
            // catching only RSF parsing exceptions and handling those
            loadResult = RSFResult.createFailResult("RSF parsing error", e);
        } catch (SerializationFormatValidationException e) {
            // catching only RSF validation exceptions and handling those
            loadResult = RSFResult.createFailResult("RSF validation error", e);
        }

        if (loadResult.isSuccessful()) {
            return Response.status(Response.Status.OK).build();
        } else {
            return Response.status(400).entity(loadResult).build();
        }
    }

    private void mintItems(Iterable<JsonNode> objects) {
        registerContext.transactionalRegisterOperation(register -> {
            AtomicInteger currentEntryNumber = new AtomicInteger(register.getTotalEntries());
            Iterables.transform(objects, Item::new).forEach(item -> mintItem(register, currentEntryNumber, item));
        });
    }

    private void mintItem(Register register, AtomicInteger currentEntryNumber, Item item) {
        register.putItem(item);
        register.appendEntry(new Entry(currentEntryNumber.incrementAndGet(), item.getSha256hex(), Instant.now(), item.getValue(this.registerContext.getRegisterName().value())));
    }
}


@@ -2823,63 +2823,8 @@
 f);%0A
-        %7D catch (SerializedRegisterParseException e) %7B%0A
     
@@ -2860,16 +2860,31 @@
 parsing 
+and validation 
 exceptio
@@ -2897,32 +2897,87 @@
  handling those%0A
+        %7D catch (SerializedRegisterParseException e) %7B%0A
             load
@@ -3102,82 +3102,8 @@
 ) %7B%0A
-            // catching only RSF validation exceptions and handling those%0A
     

Make comment clearer