package uk.gov.register.core;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import com.google.common.collect.Lists;
import uk.gov.register.util.HashValue;
import uk.gov.register.util.ISODateFormatter;
import uk.gov.register.views.CsvRepresentationView;
import uk.gov.register.views.representations.CsvRepresentation;

import java.time.Instant;
import java.util.Iterator;
import java.util.List;

@JsonIgnoreProperties(ignoreUnknown=true)
@JsonPropertyOrder({"entry-number", "entry-timestamp", "item-hash", "key"})
public class Entry implements CsvRepresentationView<Entry> {
    private final int entryNumber;
    private final HashValue hashValue;
    private final Instant timestamp;
    private String key;

    public Entry(int entryNumber, HashValue hashValue, Instant timestamp, String key) {
        this.entryNumber = entryNumber;
        this.hashValue = hashValue;
        this.timestamp = timestamp;
        this.key = key;
    }

    @JsonIgnore
    public Instant getTimestamp() {
        return timestamp;
    }

    @SuppressWarnings("unused, used from DAO")
    @JsonProperty("item-hash")
    public HashValue getSha256hex() {
        return hashValue;
    }

    @JsonIgnore
    public long getTimestampAsLong() {
        return timestamp.getEpochSecond();
    }

    @JsonProperty("entry-number")
    @JsonSerialize(using = ToStringSerializer.class)
    public Integer getEntryNumber() {
        return entryNumber;
    }

    @JsonProperty("entry-timestamp")
    public String getTimestampAsISOFormat() {
        return ISODateFormatter.format(timestamp);
    }

    @JsonProperty("key")
    public String getKey() {
        return key;
    }

    public static CsvSchema csvSchema() {
        CsvMapper csvMapper = new CsvMapper();
        csvMapper.disable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
        return csvMapper.schemaFor(Entry.class);
    }

    public static CsvSchema csvSchemaWithOmittedFields(List<String> fieldsToRemove) {
        CsvSchema originalSchema = csvSchema();
        Iterator<CsvSchema.Column> columns = originalSchema.rebuild().getColumns();

        List<CsvSchema.Column> updatedColumns = Lists.newArrayList(columns);
        updatedColumns.removeIf(c -> fieldsToRemove.contains(c.getName()));

        return CsvSchema.builder().addColumns(updatedColumns).build();
    }

    @Override
    public CsvRepresentation<Entry> csvRepresentation() {
        return new CsvRepresentation<>(csvSchema(), this);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Entry entry = (Entry) o;

        if (entryNumber != entry.entryNumber) return false;
        return hashValue == null ? entry.hashValue == null : hashValue.equals(entry.hashValue);
    }

    @Override
    public int hashCode() {
        int result = hashValue != null ? hashValue.hashCode() : 0;
        result = 31 * entryNumber + result;
        return result;
    }
}

@@ -812,16 +812,41 @@
 nstant;%0A
+import java.util.Arrays;%0A
 import j
@@ -864,16 +864,16 @@
 erator;%0A
-
 import j
@@ -1120,16 +1120,21 @@
 e final 
+List%3C
 HashValu
@@ -1126,32 +1126,33 @@
 l List%3CHashValue
+%3E
  hashValue;%0A    
@@ -1141,24 +1141,25 @@
 e%3E hashValue
+s
 ;%0A    privat
@@ -1360,16 +1360,271 @@
 ashValue
+s = Arrays.asList(hashValue);%0A        this.timestamp = timestamp;%0A        this.key = key;%0A    %7D%0A%0A    public Entry(int entryNumber, List%3CHashValue%3E hashValues, Instant timestamp, String key) %7B%0A        this.entryNumber = entryNumber;%0A        this.hashValues
  = hashV
@@ -1623,24 +1623,25 @@
  = hashValue
+s
 ;%0A        th
@@ -1894,24 +1894,24 @@
 a256hex() %7B%0A
-
         retu
@@ -1922,16 +1922,119 @@
 ashValue
+s.get(0);%0A    %7D%0A%0A    @JsonIgnore%0A    public List%3CHashValue%3E getItemHashes() %7B%0A        return hashValues
 ;%0A    %7D%0A
@@ -3594,32 +3594,33 @@
 return hashValue
+s
  == null ? entry
@@ -3629,16 +3629,17 @@
 ashValue
+s
  == null
@@ -3650,16 +3650,17 @@
 ashValue
+s
 .equals(
@@ -3670,24 +3670,25 @@
 ry.hashValue
+s
 );%0A    %7D%0A%0A  
@@ -3757,16 +3757,17 @@
 ashValue
+s
  != null
@@ -3778,16 +3778,17 @@
 ashValue
+s
 .hashCod

Add support to Entry for multiple item hashes