package rx.broadcast;

import org.jetbrains.annotations.NotNull;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Objects;
import java.util.Set;
import java.util.stream.IntStream;
import java.util.stream.Stream;

final class VectorTimestamp implements Comparable<VectorTimestamp>, Serializable {
    private static final long serialVersionUID = 114L;

    private Sender[] ids;

    private long[] timestamps;

    @SuppressWarnings("unused")
    VectorTimestamp() {

    }

    VectorTimestamp(final Sender[] ids, final long[] timestamps) {
        if (ids.length != timestamps.length) {
            throw new IllegalArgumentException("IDs and timestamps must contain the same number of elements");
        }

        this.ids = ids;
        this.timestamps = timestamps;
    }

    Stream<VectorTimestampEntry> stream() {
        return IntStream.range(0, ids.length).mapToObj(idx -> new VectorTimestampEntry(ids[idx], timestamps[idx]));
    }

    @Override
    public String toString() {
        return Arrays.toString(stream().map(VectorTimestampEntry::toString).toArray());
    }

    @SuppressWarnings({"checkstyle:AvoidInlineConditionals"})
    @Override
    public final int compareTo(@NotNull final VectorTimestamp other) {
        final HashMap<Sender, Long> vt1 = new HashMap<>();
        for (int i = 0; i < ids.length; i++) {
            vt1.put(ids[i], timestamps[i]);
        }

        final HashMap<Sender, Long> vt2 = new HashMap<>();
        for (int i = 0; i < other.ids.length; i++) {
            vt2.put(other.ids[i], other.timestamps[i]);
        }

        final Set<Sender> senders = vt1.keySet();
        final boolean lte = senders.stream().allMatch(
            (sender) -> vt2.containsKey(sender) && vt1.get(sender) <= vt2.get(sender));
        final boolean lt  = senders.stream().anyMatch(
            (sender) -> vt2.containsKey(sender) && vt1.get(sender) <  vt2.get(sender)) && lte;
        return lt ? -1 : lte ? 0 : 1;
    }

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

        final VectorTimestamp timestamp = (VectorTimestamp) o;
        return this.compareTo(timestamp) == 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(ids, timestamps);
    }
}

@@ -1688,19 +1688,35 @@
 boolean 
-lte
+allAreLessThanOrEql
  = sende
@@ -1730,18 +1730,8 @@
 am()
-.allMatch(
 %0A   
@@ -1735,39 +1735,44 @@
             
-(sender
+.allMatch((s
 ) -%3E vt
-2
+1
 .containsKey
@@ -1765,37 +1765,54 @@
 t1.containsKey(s
-ender
+) && vt2.containsKey(s
 ) && vt1.get(sen
@@ -1809,21 +1809,16 @@
 t1.get(s
-ender
 ) %3C= vt2
@@ -1823,21 +1823,16 @@
 t2.get(s
-ender
 ));%0A    
@@ -1849,19 +1849,35 @@
 boolean 
-lt 
+oneExistsThatIsLess
  = sende
@@ -1891,18 +1891,8 @@
 am()
-.anyMatch(
 %0A   
@@ -1904,23 +1904,28 @@
     
-(sender
+.anyMatch((s
 ) -%3E vt
-2
+1
 .con
@@ -1934,21 +1934,38 @@
 insKey(s
-ender
+) && vt2.containsKey(s
 ) && vt1
@@ -1970,21 +1970,16 @@
 t1.get(s
-ender
 ) %3C  vt2
@@ -1988,22 +1988,10 @@
 et(s
-ender)) && lte
+))
 ;%0A  
@@ -2007,21 +2007,79 @@
 urn 
-lt ? -1 : lte
+(oneExistsThatIsLess && allAreLessThanOrEql) ? -1 : allAreLessThanOrEql
  ? 0

Rewrite VT#compareTo for static analyzer