package uk.gov.register.presentation.resource;

import uk.gov.register.presentation.DbRecord;
import uk.gov.register.presentation.dao.RecentEntryIndexQueryDAO;
import uk.gov.register.presentation.representations.ExtraMediaType;
import uk.gov.register.presentation.view.SingleResultView;
import uk.gov.register.presentation.view.ViewFactory;

import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.Optional;


@Path("/")
public class SearchResource {

    protected final RequestContext requestContext;
    private final ViewFactory viewFactory;
    private final RecentEntryIndexQueryDAO queryDAO;

    @Inject
    public SearchResource(ViewFactory viewFactory, RequestContext requestContext, RecentEntryIndexQueryDAO queryDAO) {
        this.requestContext = requestContext;
        this.viewFactory = viewFactory;
        this.queryDAO = queryDAO;
    }

    @GET
    @Path("/{primaryKey}/{primaryKeyValue}")
    @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON, ExtraMediaType.TEXT_YAML, ExtraMediaType.TEXT_CSV, ExtraMediaType.TEXT_TSV, ExtraMediaType.TEXT_TTL})
    public SingleResultView findByPrimaryKey(@PathParam("primaryKey") String key, @PathParam("primaryKeyValue") String value) {
        if (key.equals(requestContext.getRegisterPrimaryKey())) {
            Optional<DbRecord> record = queryDAO.findByKeyValue(key, value);
            if (record.isPresent()) {
                setVersionHistoryLinkHeader(record.get());
                return viewFactory.getSingleResultView(record.get());
            }
        }

        throw new NotFoundException();
    }

    @GET
    @Path("/hash/{hash}")
    @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON, ExtraMediaType.TEXT_YAML, ExtraMediaType.TEXT_CSV, ExtraMediaType.TEXT_TSV, ExtraMediaType.TEXT_TTL})
    public SingleResultView findByHash(@PathParam("hash") String hash) {
        Optional<DbRecord> optionalRecord = queryDAO.findByHash(hash);
        if (optionalRecord.isPresent()) {
            DbRecord record = optionalRecord.get();

            setVersionHistoryLinkHeader(record);

            return viewFactory.getSingleResultView(record);
        }
        throw new NotFoundException();
    }

    private void setVersionHistoryLinkHeader(DbRecord record) {
        String primaryKey = requestContext.getRegisterPrimaryKey();
        requestContext.
                getHttpServletResponse().
                setHeader("Link", String.format("</%s/%s/history>;rel=\"version-history\"",
                        primaryKey,
                        record.getEntry().get(primaryKey).textValue()));
    }

    @GET
    @Path("/entry/{serial}")
    public SingleResultView findBySerial(@PathParam("serial") int serial) {
        Optional<DbRecord> recordO = queryDAO.findBySerial(serial);
        recordO.ifPresent(this::setVersionHistoryLinkHeader);
        return recordO.map(viewFactory::getSingleResultView)
                .orElseThrow(NotFoundException::new);
    }
}

@@ -1257,16 +1257,17 @@
     if (
+!
 key.equa
@@ -1308,32 +1308,81 @@
 ryKey())) %7B%0A    
+        throw new NotFoundException();%0A        %7D%0A
         Optional
@@ -1394,24 +1394,25 @@
 cord%3E record
+O
  = queryDAO.
@@ -1451,228 +1451,37 @@
     
-    if (record.isPresent()) %7B%0A                setVersionHistoryLinkHeader(record.get());%0A                return viewFactory.getSingleResultView(record.get());%0A            %7D%0A        %7D%0A%0A        throw new NotFoundException(
+return recordResponse(recordO
 );%0A 
@@ -1787,30 +1787,23 @@
 Record%3E 
-optionalR
+r
 ecord
+O
  = query
@@ -1836,38 +1836,157 @@
     
-if (optionalRecord.isPresent()
+return recordResponse(recordO);%0A    %7D%0A%0A    @GET%0A    @Path(%22/entry/%7Bserial%7D%22)%0A    public SingleResultView findBySerial(@PathParam(%22serial%22) int serial
 ) %7B%0A
@@ -1997,20 +1997,25 @@
     
-    
+Optional%3C
 DbRecord
  rec
@@ -2014,53 +2014,218 @@
 cord
+%3E
  record
+O
  = 
-optionalRecord.get();%0A%0A            
+queryDAO.findBySerial(serial);%0A        return recordResponse(recordO);%0A    %7D%0A%0A    private SingleResultView recordResponse(Optional%3CDbRecord%3E optionalRecord) %7B%0A        optionalRecord.ifPresent(this::
 setV
@@ -2251,29 +2251,19 @@
 ader
-(record);%0A%0A  
+);%0A
         
   re
@@ -2258,25 +2258,42 @@
         
-  
 return 
+optionalRecord.map(
 viewFact
@@ -2295,17 +2295,18 @@
 wFactory
-.
+::
 getSingl
@@ -2320,17 +2320,9 @@
 View
-(record);
+)
 %0A   
@@ -2326,26 +2326,24 @@
         
-%7D%0A
         
 throw ne
@@ -2330,34 +2330,37 @@
             
-throw new 
+.orElseThrow(
 NotFoundExce
@@ -2360,25 +2360,29 @@
 undException
-(
+::new
 );%0A    %7D%0A%0A  
@@ -2787,373 +2787,7 @@
    %7D
-%0A%0A    @GET%0A    @Path(%22/entry/%7Bserial%7D%22)%0A    public SingleResultView findBySerial(@PathParam(%22serial%22) int serial) %7B%0A        Optional%3CDbRecord%3E recordO = queryDAO.findBySerial(serial);%0A        recordO.ifPresent(this::setVersionHistoryLinkHeader);%0A        return recordO.map(viewFactory::getSingleResultView)%0A                .orElseThrow(NotFoundException::new);%0A    %7D
 %0A%7D%0A

remove duplicate logic