package org.gbif.registry.ws.client;

import org.gbif.api.model.common.paging.Pageable;
import org.gbif.api.model.common.paging.PagingResponse;
import org.gbif.api.model.occurrence.Download;
import org.gbif.api.model.registry.DatasetOccurrenceDownloadUsage;
import org.gbif.api.service.registry.OccurrenceDownloadService;
import org.gbif.api.vocabulary.Country;
import org.gbif.registry.ws.client.guice.RegistryWs;
import org.gbif.ws.client.BaseWsGetClient;

import java.text.SimpleDateFormat;
import java.util.*;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import javax.ws.rs.core.MultivaluedMap;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.ClientFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl;

/**
 * OccurrenceDownloadService web service client.
 */
public class OccurrenceDownloadWsClient extends BaseWsGetClient<Download, String> implements
  OccurrenceDownloadService {

  private MultivaluedMap<String,String> buildStatusParam(Set<Download.Status> status){
    MultivaluedMap<String,String> statuses = null;
    if(status != null && !status.isEmpty()) {
      statuses = new MultivaluedMapImpl();
      statuses.put("status", Lists.newArrayList(Collections2.transform(status,new Function<Download.Status, String>() {
        @Nullable
        @Override
        public String apply(@Nullable Download.Status input) {
          return input.name();
        }
      })));
    }
    return statuses;
  }

  @Inject
  public OccurrenceDownloadWsClient(@RegistryWs WebResource resource, @Nullable ClientFilter authFilter) {
    super(Download.class, resource.path("occurrence/download"), authFilter);
  }

  @Override
  public void update(Download download) {
    put(download, download.getKey());
  }

  @Override
  public void create(Download occurrenceDownload) {
    post(occurrenceDownload, "/");
  }

  @Override
  public PagingResponse<Download> list(@Nullable Pageable page, @Nullable Set<Download.Status> status) {
     return get(GenericTypes.PAGING_OCCURRENCE_DOWNLOAD, null, buildStatusParam(status), page);
  }

  @Override
  public PagingResponse<Download> listByUser(String user, Pageable page, Set<Download.Status> status) {
    return get(GenericTypes.PAGING_OCCURRENCE_DOWNLOAD, null, buildStatusParam(status), page,"user", user);
  }

  @Override
  public PagingResponse<DatasetOccurrenceDownloadUsage> listDatasetUsages(
    @NotNull String downloadKey, @Nullable Pageable page
  ) {
    return get(GenericTypes.PAGING_DATASET_OCCURRENCE_DOWNLOAD, page, downloadKey, "datasets");
  }


  @Override
  public Map<Integer,Map<Integer,Long>> getMonthlyStats(@Nullable Date fromDate, @Nullable Date toDate,
                                                        @Nullable Country userCountry,
                                                        @Nullable Country publishingCountry,
                                                        @Nullable UUID datasetKey) {
    return statsServiceCall(fromDate, toDate, userCountry, publishingCountry, datasetKey,"stats");
  }

  @Override
  public Map<Integer, Map<Integer, Long>> getDownloadedRecordsStats(@Nullable Date fromDate,
                                                                            @Nullable Date toDate,
                                                                            @Nullable Country userCountry,
                                                                            @Nullable Country publishingCountry,
                                                                            @Nullable UUID datasetKey) {
    return statsServiceCall(fromDate, toDate, userCountry, publishingCountry, datasetKey,"stats/downloadedRecords");
  }

  private Map<Integer,Map<Integer,Long>> statsServiceCall(@Nullable Date fromDate, @Nullable Date toDate,
                                                          @Nullable Country userCountry,
                                                          @Nullable Country publishingCountry,
                                                          @Nullable UUID datasetKey, String path) {
    MultivaluedMap<String, String> params = new MultivaluedMapImpl();
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
    Optional.ofNullable(fromDate).ifPresent( d -> params.add("fromDate", simpleDateFormat.format(d)));
    Optional.ofNullable(toDate).ifPresent( d -> params.add("toDate", simpleDateFormat.format(d)));
    Optional.ofNullable(userCountry).ifPresent( c -> params.add("country", c.getIso2LetterCode()));
    Optional.ofNullable(publishingCountry).ifPresent( c -> params.add("country", c.getIso2LetterCode()));
    Optional.ofNullable(datasetKey).ifPresent( dk -> params.add("datasetKey", dk.toString()));
    return get(GenericTypes.DOWNLOADS_STATS_TYPE, null, params ,null,path);
  }
}

@@ -2750,17 +2750,16 @@
 );%0A  %7D%0A%0A
-%0A
   @Overr
@@ -2775,32 +2775,33 @@
 lic Map%3CInteger,
+ 
 Map%3CInteger,Long
@@ -2792,24 +2792,25 @@
 Map%3CInteger,
+ 
 Long%3E%3E getMo
@@ -2811,20 +2811,34 @@
  get
-MonthlyStats
+DownloadedRecordsByDataset
 (@Nu
@@ -2862,32 +2862,25 @@
 ate,
- @Nullable Date toDate,%0A
+%0A                
     
@@ -2941,37 +2941,34 @@
 ullable 
-Country userCountry,%0A
+Date toDate,%0A     
         
@@ -3007,32 +3007,43 @@
                 
+           
 @Nullable Countr
@@ -3055,32 +3055,48 @@
 lishingCountry,%0A
+                
                 
@@ -3206,35 +3206,28 @@
 te, toDate, 
-userCountry
+null
 , publishing
@@ -3251,17 +3251,49 @@
 ey,%22stat
-s
+istics/downloadedRecordsByDataset
 %22);%0A  %7D%0A
@@ -3362,22 +3362,22 @@
 load
-edRecordsStats
+sByUserCountry
 (@Nu
@@ -3394,32 +3394,24 @@
 e fromDate,%0A
-        
             
@@ -3553,32 +3553,24 @@
             
-        
 @Nullable Co
@@ -3590,224 +3590,8 @@
 ntry
-,%0A                                                                            @Nullable Country publishingCountry,%0A                                                                            @Nullable UUID datasetKey
 ) %7B%0A
@@ -3653,62 +3653,53 @@
 ry, 
-publishingCountry, datasetKey,%22stats/downloadedRecords
+null, null,%22statistics/downloadsByUserCountry
 %22);%0A
@@ -4495,33 +4495,37 @@
  -%3E params.add(%22
-c
+userC
 ountry%22, c.getIs
@@ -4613,17 +4613,27 @@
 ms.add(%22
-c
+publishingC
 ountry%22,

Add statistics Java client calls.