package org.opencb.commons.datastore.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class DataResult<T> {

    private int time;

    private List<Event> events;

    private int numResults;
    private List<T> results;
    private String resultType;

    @Deprecated
    private long numTotalResults;
    private long numMatches;
    private long numInserted;
    private long numUpdated;
    private long numDeleted;

    private ObjectMap attributes;

    public DataResult() {
    }

    public DataResult(int time, List<Event> events, int numResults, List<T> results, long numMatches) {
        this(time, events, numResults, results, numMatches, 0, 0, 0, new ObjectMap());
    }

    public DataResult(int time, List<Event> events, int numResults, List<T> results, long numMatches, ObjectMap attributes) {
        this(time, events, numResults, results, numMatches, 0, 0, 0, attributes);
    }

    public DataResult(int time, List<Event> events, long numMatches, long numInserted, long numUpdated, long numDeleted) {
        this(time, events, 0, Collections.emptyList(), numMatches, numInserted, numUpdated, numDeleted, new ObjectMap());
    }

    public DataResult(int time, List<Event> events, long numMatches, long numInserted, long numUpdated, long numDeleted,
                      ObjectMap attributes) {
        this(time, events, 0, Collections.emptyList(), numMatches, numInserted, numUpdated, numDeleted, attributes);
    }

    public DataResult(int time, List<Event> events, int numResults, List<T> results, long numMatches, long numInserted, long numUpdated,
                      long numDeleted, ObjectMap attributes) {
        this.time = time;
        this.events = events;
        this.numResults = numResults;
        this.results = results;
        this.numMatches = numMatches;
        this.numInserted = numInserted;
        this.numUpdated = numUpdated;
        this.numDeleted = numDeleted;
        this.resultType = results != null && !results.isEmpty() && results.get(0) != null
                ? results.get(0).getClass().getCanonicalName() : "";
        this.attributes = attributes;
    }

    public static DataResult empty() {
        return new DataResult(0, new ArrayList<>(), 0, new ArrayList(), 0, 0, 0, 0, new ObjectMap());
    }

    public T first() {
        if (results != null && results.size() > 0) {
            return results.get(0);
        }
        return null;
    }

    public void append(DataResult dataResult) {
        this.numResults += dataResult.numResults;
        this.numMatches += dataResult.numMatches;
        this.numInserted += dataResult.numInserted;
        this.numUpdated += dataResult.numUpdated;
        this.numDeleted += dataResult.numDeleted;
        this.time += dataResult.time;

        if (this.events != null && dataResult.getEvents() != null) {
            this.events.addAll(dataResult.getEvents());
        }
        if (this.results != null && dataResult.getResults() != null) {
            this.results.addAll(dataResult.getResults());
        }
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("DataResult{");
        sb.append("time=").append(time);
        sb.append(", events=").append(events);
        sb.append(", numResults=").append(numResults);
        sb.append(", results=").append(results);
        sb.append(", numMatches=").append(numMatches);
        sb.append(", numInserted=").append(numInserted);
        sb.append(", numUpdated=").append(numUpdated);
        sb.append(", numDeleted=").append(numDeleted);
        sb.append(", attributes=").append(attributes);
        sb.append('}');
        return sb.toString();
    }

    public int getTime() {
        return time;
    }

    public DataResult<T> setTime(int time) {
        this.time = time;
        return this;
    }

    public List<Event> getEvents() {
        return events;
    }

    public DataResult<T> setEvents(List<Event> events) {
        this.events = events;
        return this;
    }

    public int getNumResults() {
        return numResults;
    }

    public DataResult<T> setNumResults(int numResults) {
        this.numResults = numResults;
        return this;
    }

    public List<T> getResults() {
        return results;
    }

    public DataResult<T> setResults(List<T> results) {
        this.results = results;
        return this;
    }

    @Deprecated
    public long getNumTotalResults() {
        return numMatches;
    }

    @Deprecated
    public DataResult<T> setNumTotalResults(long numTotalResults) {
        this.numMatches = numTotalResults;
        return this;
    }

    public long getNumMatches() {
        return numMatches;
    }

    public DataResult<T> setNumMatches(long numMatches) {
        this.numMatches = numMatches;
        return this;
    }

    public long getNumInserted() {
        return numInserted;
    }

    public DataResult<T> setNumInserted(long numInserted) {
        this.numInserted = numInserted;
        return this;
    }

    public long getNumUpdated() {
        return numUpdated;
    }

    public DataResult<T> setNumUpdated(long numUpdated) {
        this.numUpdated = numUpdated;
        return this;
    }

    public long getNumDeleted() {
        return numDeleted;
    }

    public DataResult<T> setNumDeleted(long numDeleted) {
        this.numDeleted = numDeleted;
        return this;
    }

    public String getResultType() {
        return resultType;
    }

    public DataResult<T> setResultType(String resultType) {
        this.resultType = resultType;
        return this;
    }

    public ObjectMap getAttributes() {
        return attributes;
    }

    public DataResult<T> setAttributes(ObjectMap attributes) {
        this.attributes = attributes;
        return this;
    }
}

@@ -151,29 +151,31 @@
 T%3E %7B%0A%0A    pr
-ivate
+otected
  int time;%0A%0A
@@ -176,29 +176,31 @@
 ime;%0A%0A    pr
-ivate
+otected
  List%3CEvent%3E
@@ -215,21 +215,23 @@
 %0A%0A    pr
-ivate
+otected
  int num
@@ -245,21 +245,23 @@
 ;%0A    pr
-ivate
+otected
  List%3CT%3E
@@ -276,21 +276,23 @@
 ;%0A    pr
-ivate
+otected
  String 
@@ -352,37 +352,39 @@
 lResults;%0A    pr
-ivate
+otected
  long numMatches
@@ -383,37 +383,39 @@
 mMatches;%0A    pr
-ivate
+otected
  long numInserte
@@ -415,37 +415,39 @@
 Inserted;%0A    pr
-ivate
+otected
  long numUpdated
@@ -450,29 +450,31 @@
 ated;%0A    pr
-ivate
+otected
  long numDel
@@ -486,21 +486,23 @@
 %0A%0A    pr
-ivate
+otected
  ObjectM

change visibility of DataResult attributes