/*
 * Druid - a distributed column store.
 * Copyright (C) 2012  Metamarkets Group Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package com.metamx.druid.http;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.metamx.druid.client.ClientInventoryManager;
import com.metamx.druid.client.DataSegment;
import com.metamx.druid.client.DruidDataSource;
import com.metamx.druid.client.DruidServer;
import org.joda.time.DateTime;
import org.joda.time.Interval;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 */
@Path("/datasources")
public class ClientInfoResource
{
  private static final int SEGMENT_HISTORY_MILLIS = 7 * 24 * 60 * 60 * 1000; // ONE WEEK

  private ClientInventoryManager clientInventoryManager;

  @Inject
  public ClientInfoResource(
      ClientInventoryManager clientInventoryManager
  )
  {
    this.clientInventoryManager = clientInventoryManager;
  }

  private Map<String, List<DataSegment>> getSegmentsForDatasources()
  {
    final Map<String, List<DataSegment>> dataSourceMap = Maps.newHashMap();
    for (DruidServer server : clientInventoryManager.getInventory()) {
      for (DruidDataSource dataSource : server.getDataSources()) {
        if (!dataSourceMap.containsKey(dataSource.getName())) {
          dataSourceMap.put(dataSource.getName(), Lists.<DataSegment>newArrayList());
        }
        List<DataSegment> segments = dataSourceMap.get(dataSource.getName());
        segments.addAll(dataSource.getSegments());
      }
    }
    return dataSourceMap;
  }

  @GET
  @Produces("application/json")
  public Iterable<String> getDataSources()
  {
    return getSegmentsForDatasources().keySet();
  }

  @GET
  @Path("/{dataSourceName}")
  @Produces("application/json")
  public Map<String, Object> getDatasource(
      @PathParam("dataSourceName") String dataSourceName,
      @QueryParam("interval") Interval interval
  )
  {
    return ImmutableMap.<String, Object>of(
        "dimensions", getDatasourceDimensions(dataSourceName, interval),
        "metrics", getDatasourceMetrics(dataSourceName, interval)
    );
  }

  @GET
  @Path("/{dataSourceName}/dimensions")
  @Produces("application/json")
  public Iterable<String> getDatasourceDimensions(
      @PathParam("dataSourceName") String dataSourceName,
      @QueryParam("interval") Interval interval
  )
  {
    List<DataSegment> segments = getSegmentsForDatasources().get(dataSourceName);

    if (interval == null) {
      DateTime now = new DateTime();
      interval = new Interval(now.minusMillis(SEGMENT_HISTORY_MILLIS), now);
    }

    Set<String> dims = Sets.newHashSet();
    for (DataSegment segment : segments) {
      if (interval.overlaps(segment.getInterval())) {
        dims.addAll(segment.getDimensions());
      }
    }

    return dims;
  }

  @GET
  @Path("/{dataSourceName}/metrics")
  @Produces("application/json")
  public Iterable<String> getDatasourceMetrics(
      @PathParam("dataSourceName") String dataSourceName,
      @QueryParam("interval") Interval interval
  )
  {
    List<DataSegment> segments = getSegmentsForDatasources().get(dataSourceName);

    if (interval == null) {
      DateTime now = new DateTime();
      interval = new Interval(now.minusMillis(SEGMENT_HISTORY_MILLIS), now);
    }

    Set<String> metrics = Sets.newHashSet();
    for (DataSegment segment : segments) {
      if (interval.overlaps(segment.getInterval())) {
        metrics.addAll(segment.getMetrics());
      }
    }

    return metrics;
  }
}

@@ -2830,32 +2830,30 @@
 %22interval%22) 
-Interval
+String
  interval%0A  
@@ -3267,32 +3267,30 @@
 %22interval%22) 
-Interval
+String
  interval%0A  
@@ -3382,36 +3382,84 @@
 );%0A%0A    
-if (interval == null
+Interval theInterval;%0A    if (interval == null %7C%7C interval.isEmpty()
 ) %7B%0A    
@@ -3489,33 +3489,36 @@
 teTime();%0A      
-i
+theI
 nterval = new In
@@ -3568,32 +3568,89 @@
 IS), now);%0A    %7D
+ else %7B%0A      theInterval = new Interval(interval);%0A    %7D
 %0A%0A    Set%3CString
@@ -3722,33 +3722,36 @@
 ts) %7B%0A      if (
-i
+theI
 nterval.overlaps
@@ -4072,24 +4072,22 @@
 erval%22) 
-Interval
+String
  interva
@@ -4183,36 +4183,84 @@
 );%0A%0A    
-if (interval == null
+Interval theInterval;%0A    if (interval == null %7C%7C interval.isEmpty()
 ) %7B%0A    
@@ -4298,17 +4298,20 @@
 ;%0A      
-i
+theI
 nterval 
@@ -4369,32 +4369,89 @@
 IS), now);%0A    %7D
+ else %7B%0A      theInterval = new Interval(interval);%0A    %7D
 %0A%0A    Set%3CString
@@ -4530,25 +4530,28 @@
 %7B%0A      if (
-i
+theI
 nterval.over

fix a bug with client info resource with guice