package org.zalando.catwatch.backend.util;

import org.zalando.catwatch.backend.model.Contributor;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.util.*;

/**
 * Class to collect the statistics of the contributors
 *
 * Created by nwang on 13/08/15.
 */
public class ContributorStats {
    private String name;
    private String organizationName;
    private String url;
    private List<Integer> organizationalCommitsCounts;
    private List<Integer> personalCommitsCounts;
    private List<Integer> organizationalProjectsCounts;
    private List<Integer> personalProjectsCounts;
    private List<Date> snapshotDates;

    public ContributorStats(List<Contributor> contributions) {
        Contributor first = contributions.get(0);
        name = first.getName();
        organizationName = first.getOrganizationName();
        url = first.getUrl();
        contributions.sort((o1, o2) -> o1.getSnapshotDate().compareTo(o2.getSnapshotDate()));
        int size = contributions.size();
        organizationalCommitsCounts = new ArrayList<>(size);
        personalCommitsCounts = new ArrayList<>(size);
        organizationalProjectsCounts = new ArrayList<>(size);
        personalProjectsCounts = new ArrayList<>(size);
        snapshotDates = new ArrayList<>(size);
        int i = 0;
        Date lastSnapshotDate = null;
        for (Contributor c : contributions) {
            if (c.getId() != first.getId()) {
                throw new IllegalArgumentException("All the contributors in the list must have the same name.");
            }
            if (lastSnapshotDate == null || !c.getSnapshotDate().equals(lastSnapshotDate)) {
                organizationalCommitsCounts.add(i, c.getOrganizationalCommitsCount());
                personalCommitsCounts.add(i, c.getPersonalCommitsCount());
                organizationalProjectsCounts.add(i, c.getOrganizationalProjectsCount());
                personalProjectsCounts.add(i, c.getPersonalProjectsCount());
                snapshotDates.add(i, c.getSnapshotDate());
                i++;
            }
            lastSnapshotDate = c.getSnapshotDate();
        }
    }

    @JsonProperty(value="name")
    public String getName() {return name;}

    @JsonProperty(value="organization_name")
    public String getOrganizationName() {return organizationName;}

    @JsonProperty(value="url")
    public String getUrl() {return url;}

    @JsonProperty(value="organization_commit_counts")
    public List<Integer> getOrganizationalCommitsCounts() {return organizationalCommitsCounts;}

    @JsonProperty(value="personal_commit_counts")
    public List<Integer> getPersonalCommitsCounts() {return personalCommitsCounts;}

    @JsonProperty(value="organization_project_counts")
    public List<Integer> getOrganizationalProjectsCounts() {return organizationalProjectsCounts;}

    @JsonProperty(value="personal_project_counts")
    public List<Integer> getPersonalProjectsCounts() {return personalProjectsCounts;}

    @JsonProperty(value="snapshot_dates")
    @JsonSerialize(using = JsonDateListSerializer.class)
    public List<Date> getSnapshotDates() { return snapshotDates; }

    public static List<ContributorStats> buildStats(List<Contributor> contributors) {
        Map<String, List<Contributor>> contributorByID = getDistinctContributors(contributors);
        List<ContributorStats> result = new LinkedList<>();
        for (List<Contributor> contributions : contributorByID.values()) {
            result.add(new ContributorStats(contributions));
        }
        return result;
    }

    public static Map<String, List<Contributor>> getDistinctContributors(List<Contributor> contributors) {
        Map<String, List<Contributor>> result = new HashMap<>();
        for (Contributor contributor : contributors) {
            String id = String.valueOf(contributor.getId());
            List<Contributor> list = result.get(id);
            if (list == null) {
                list = new LinkedList<>();
                result.put(id, list);
            }
            list.add(contributor);
        }
        return result;
    }

    @Override
    public String toString() {
        return String.format(
                "ContributorStats(%s, %s, %s, %s)", name, organizationName, url, snapshotDates);
    }
}

@@ -294,16 +294,279 @@
 tors%0A *%0A
+ * This class collect the statistics from a List of Contributor objects and%0A * put them in a more compact way.%0A * Specifically, the fields which have always the same value are storaged for%0A * only once. The counts and dates are put into an array of their own.%0A *%0A
  * Creat
@@ -3471,24 +3471,350 @@
 otDates; %7D%0A%0A
+    /**%0A     * Take a list of contributors and return a list their statistics that are seperated%0A     * by different contributors.%0A     *%0A     * @param contributors  a list consisting of contributors.%0A     * @return a list, each entry of which consists of statistics of the same contributors%0A     * at different date.%0A     */%0A
     public s
@@ -4215,24 +4215,342 @@
 ult;%0A    %7D%0A%0A
+    /**%0A     * Take a list of contributors and return a map of lists where contributors have been partitioned%0A     * by id.%0A     *%0A     * @param contributors a list consisting of potentially different contributors.%0A     * @return a map which contains the list separated by contributors, using the id as index.%0A     */%0A
     public s

add some documentation for the statistics/contributors API.