// Path: src/main/java/org/killbill/billing/plugin/meter/timeline/shutdown/StartTimes.java
// public class StartTimes {
// 
//     private final DateTime timeInserted;
//     private final Map<Integer, Map<Integer, DateTime>> startTimesMap;
//     private DateTime minStartTime;
// 
//     public StartTimes(final DateTime timeInserted, final Map<Integer, Map<Integer, DateTime>> startTimesMap) {
//         this.timeInserted = timeInserted;
//         this.startTimesMap = startTimesMap;
//         DateTime minDateTime = new DateTime(Long.MAX_VALUE);
//         for (final Map<Integer, DateTime> categoryMap : startTimesMap.values()) {
//             for (final DateTime startTime : categoryMap.values()) {
//                 if (minDateTime.isAfter(startTime)) {
//                     minDateTime = startTime;
//                 }
//             }
//         }
//         this.minStartTime = minDateTime;
//     }
// 
//     public StartTimes() {
//         this.timeInserted = new DateTime();
//         minStartTime = new DateTime(Long.MAX_VALUE);
//         this.startTimesMap = new HashMap<Integer, Map<Integer, DateTime>>();
//     }
// 
//     public void addTime(final int sourceId, final int categoryId, final DateTime dateTime) {
//         Map<Integer, DateTime> sourceTimes = startTimesMap.get(sourceId);
//         if (sourceTimes == null) {
//             sourceTimes = new HashMap<Integer, DateTime>();
//             startTimesMap.put(sourceId, sourceTimes);
//         }
//         sourceTimes.put(categoryId, dateTime);
//         if (dateTime.isBefore(minStartTime)) {
//             minStartTime = dateTime;
//         }
//     }
// 
//     public DateTime getStartTimeForSourceIdAndCategoryId(final int sourceId, final int categoryId) {
//         final Map<Integer, DateTime> sourceTimes = startTimesMap.get(sourceId);
//         if (sourceTimes != null) {
//             return sourceTimes.get(categoryId);
//         } else {
//             return null;
//         }
//     }
// 
//     public Map<Integer, Map<Integer, DateTime>> getStartTimesMap() {
//         return startTimesMap;
//     }
// 
//     public DateTime getTimeInserted() {
//         return timeInserted;
//     }
// 
//     public DateTime getMinStartTime() {
//         return minStartTime;
//     }
// }


import com.google.common.collect.BiMap;
import java.util.List;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.killbill.billing.plugin.meter.timeline.categories.CategoryRecordIdAndMetric;
import org.killbill.billing.plugin.meter.timeline.chunks.TimelineChunk;
import org.killbill.billing.plugin.meter.timeline.consumer.TimelineChunkConsumer;
import org.killbill.billing.plugin.meter.timeline.shutdown.StartTimes;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.TenantContext;
import org.skife.jdbi.v2.exceptions.CallbackFailedException;
import org.skife.jdbi.v2.exceptions.UnableToObtainConnectionException;
/*
 * Copyright 2010-2014 Ning, Inc.
 * Copyright 2014 The Billing Project, LLC
 *
 * Ning licenses this file to you under the Apache License, version 2.0
 * (the "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at:
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package org.killbill.billing.plugin.meter.timeline.persistent;





public interface TimelineDao {

    // Sources table

    Integer getSourceId(String source, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    String getSource(Integer sourceId, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    BiMap<Integer, String> getSources(TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    int getOrAddSource(String source, CallContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    // Event categories table

    Integer getEventCategoryId(String eventCategory, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    String getEventCategory(Integer eventCategoryId, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    BiMap<Integer, String> getEventCategories(TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    int getOrAddEventCategory(String eventCategory, CallContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    // Metrics table

    Integer getMetricId(int eventCategory, String metric, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    CategoryRecordIdAndMetric getCategoryIdAndMetric(Integer metricId, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    BiMap<Integer, CategoryRecordIdAndMetric> getMetrics(TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    int getOrAddMetric(Integer eventCategoryId, String metric, CallContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    // Timelines tables

    Long insertTimelineChunk(TimelineChunk timelineChunk, CallContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    void getSamplesBySourceIdsAndMetricIds(List<Integer> sourceIds,
                                           @Nullable List<Integer> metricIds,
                                           DateTime startTime,
                                           DateTime endTime,
                                           TimelineChunkConsumer chunkConsumer,
                                           TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

// Path: src/main/java/org/killbill/billing/plugin/meter/timeline/shutdown/StartTimes.java
// public class StartTimes {
// 
//     private final DateTime timeInserted;
//     private final Map<Integer, Map<Integer, DateTime>> startTimesMap;
//     private DateTime minStartTime;
// 
//     public StartTimes(final DateTime timeInserted, final Map<Integer, Map<Integer, DateTime>> startTimesMap) {
//         this.timeInserted = timeInserted;
//         this.startTimesMap = startTimesMap;
//         DateTime minDateTime = new DateTime(Long.MAX_VALUE);
//         for (final Map<Integer, DateTime> categoryMap : startTimesMap.values()) {
//             for (final DateTime startTime : categoryMap.values()) {
//                 if (minDateTime.isAfter(startTime)) {
//                     minDateTime = startTime;
//                 }
//             }
//         }
//         this.minStartTime = minDateTime;
//     }
// 
//     public StartTimes() {
//         this.timeInserted = new DateTime();
//         minStartTime = new DateTime(Long.MAX_VALUE);
//         this.startTimesMap = new HashMap<Integer, Map<Integer, DateTime>>();
//     }
// 
//     public void addTime(final int sourceId, final int categoryId, final DateTime dateTime) {
//         Map<Integer, DateTime> sourceTimes = startTimesMap.get(sourceId);
//         if (sourceTimes == null) {
//             sourceTimes = new HashMap<Integer, DateTime>();
//             startTimesMap.put(sourceId, sourceTimes);
//         }
//         sourceTimes.put(categoryId, dateTime);
//         if (dateTime.isBefore(minStartTime)) {
//             minStartTime = dateTime;
//         }
//     }
// 
//     public DateTime getStartTimeForSourceIdAndCategoryId(final int sourceId, final int categoryId) {
//         final Map<Integer, DateTime> sourceTimes = startTimesMap.get(sourceId);
//         if (sourceTimes != null) {
//             return sourceTimes.get(categoryId);
//         } else {
//             return null;
//         }
//     }
// 
//     public Map<Integer, Map<Integer, DateTime>> getStartTimesMap() {
//         return startTimesMap;
//     }
// 
//     public DateTime getTimeInserted() {
//         return timeInserted;
//     }
// 
//     public DateTime getMinStartTime() {
//         return minStartTime;
//     }
// }


// Path: src/main/java/org/killbill/billing/plugin/meter/timeline/persistent/TimelineDao.java
import com.google.common.collect.BiMap;
import java.util.List;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.killbill.billing.plugin.meter.timeline.categories.CategoryRecordIdAndMetric;
import org.killbill.billing.plugin.meter.timeline.chunks.TimelineChunk;
import org.killbill.billing.plugin.meter.timeline.consumer.TimelineChunkConsumer;
import org.killbill.billing.plugin.meter.timeline.shutdown.StartTimes;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.TenantContext;
import org.skife.jdbi.v2.exceptions.CallbackFailedException;
import org.skife.jdbi.v2.exceptions.UnableToObtainConnectionException;

/*
 * Copyright 2010-2014 Ning, Inc.
 * Copyright 2014 The Billing Project, LLC
 *
 * Ning licenses this file to you under the Apache License, version 2.0
 * (the "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at:
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package org.killbill.billing.plugin.meter.timeline.persistent;





public interface TimelineDao {

    // Sources table

    Integer getSourceId(String source, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    String getSource(Integer sourceId, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    BiMap<Integer, String> getSources(TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    int getOrAddSource(String source, CallContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    // Event categories table

    Integer getEventCategoryId(String eventCategory, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    String getEventCategory(Integer eventCategoryId, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    BiMap<Integer, String> getEventCategories(TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    int getOrAddEventCategory(String eventCategory, CallContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    // Metrics table

    Integer getMetricId(int eventCategory, String metric, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    CategoryRecordIdAndMetric getCategoryIdAndMetric(Integer metricId, TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    BiMap<Integer, CategoryRecordIdAndMetric> getMetrics(TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    int getOrAddMetric(Integer eventCategoryId, String metric, CallContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    // Timelines tables

    Long insertTimelineChunk(TimelineChunk timelineChunk, CallContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    void getSamplesBySourceIdsAndMetricIds(List<Integer> sourceIds,
                                           @Nullable List<Integer> metricIds,
                                           DateTime startTime,
                                           DateTime endTime,
                                           TimelineChunkConsumer chunkConsumer,
                                           TenantContext context) throws UnableToObtainConnectionException, CallbackFailedException;

    Integer insertLastStartTimes(StartTimes startTimes, CallContext context);