/*
 * Copyright 1999-2015 dangdang.com.
 * <p>
 * Licensed 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.
 * </p>
 */

package com.dangdang.ddframe.rdb.sharding.merger.pipeline.reducer;

import com.dangdang.ddframe.rdb.sharding.merger.ResultSetMergeContext;
import com.dangdang.ddframe.rdb.sharding.merger.resultset.delegate.AbstractDelegateResultSet;
import com.dangdang.ddframe.rdb.sharding.merger.resultset.memory.row.OrderByResultSetRow;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.OrderItem;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * 流式排序的聚集结果集.
 *
 * @author gaohongtao
 * @author zhangliang
 */
@Slf4j
public final class StreamingOrderByReducerResultSet extends AbstractDelegateResultSet {
    
    private final Queue<ResultSetOrderByWrapper> delegateResultSetQueue;
    
    private final List<OrderItem> orderItems;
    
    public StreamingOrderByReducerResultSet(final ResultSetMergeContext resultSetMergeContext) throws SQLException {
        super(resultSetMergeContext.getShardingResultSets().getResultSets());
        delegateResultSetQueue = new PriorityQueue<>(getResultSets().size());
        orderItems = resultSetMergeContext.getCurrentOrderByKeys();
    }
    
    @Override
    protected boolean firstNext() throws SQLException {
        for (ResultSet each : getResultSets()) {
            ResultSetOrderByWrapper wrapper = new ResultSetOrderByWrapper(each);
            if (wrapper.next()) {
                delegateResultSetQueue.offer(wrapper);
            }
        }
        return doNext();
    }
    
    @Override
    protected boolean afterFirstNext() throws SQLException {
        ResultSetOrderByWrapper firstResultSet = delegateResultSetQueue.poll();
        setDelegate(firstResultSet.resultSet);
        if (firstResultSet.next()) {
            delegateResultSetQueue.offer(firstResultSet);
        }
        return doNext();
    }
    
    private boolean doNext() {
        if (delegateResultSetQueue.isEmpty()) {
            return false;
        }
        setDelegate(delegateResultSetQueue.peek().resultSet);
        log.trace("Chosen order by value: {}, current result set hashcode: {}", delegateResultSetQueue.peek().row, getDelegate().hashCode());
        return true;
    }
    
    @RequiredArgsConstructor
    private class ResultSetOrderByWrapper implements Comparable<ResultSetOrderByWrapper> {
        
        private final ResultSet resultSet;
        
        private OrderByResultSetRow row;
        
        boolean next() throws SQLException {
            boolean result = resultSet.next();
            if (result) {
                row = new OrderByResultSetRow(resultSet, orderItems);
            }
            return result;
        }
        
        @Override
        public int compareTo(final ResultSetOrderByWrapper o) {
            return row.compareTo(o.row);
        }
    }
}

@@ -1416,50 +1416,37 @@
 eue%3C
-ResultSetOrderByWrapper%3E delegateResultSet
+ComparableResultSet%3E priority
 Queu
@@ -1707,33 +1707,24 @@
         
-delegateResultSet
+priority
 Queue = 
@@ -1982,69 +1982,73 @@
     
-ResultSetOrderByWrapper wrapper = new ResultSetOrderByWrapper
+ComparableResultSet comparableResultSet = new ComparableResultSet
 (eac
@@ -2067,23 +2067,35 @@
     if (
-wrapper
+comparableResultSet
 .next())
@@ -2117,44 +2117,47 @@
     
-delegateResultSetQueue.offer(wrapper
+priorityQueue.offer(comparableResultSet
 );%0A 
@@ -2186,34 +2186,35 @@
 %0A        return 
-do
+has
 Next();%0A    %7D%0A  
@@ -2299,39 +2299,35 @@
         
-ResultSetOrderByWrapper
+ComparableResultSet
  firstRe
@@ -2336,33 +2336,24 @@
 ltSet = 
-delegateResultSet
+priority
 Queue.po
@@ -2454,33 +2454,24 @@
         
-delegateResultSet
+priority
 Queue.of
@@ -2516,18 +2516,19 @@
  return 
-do
+has
 Next();%0A
@@ -2562,10 +2562,11 @@
 ean 
-do
+has
 Next
@@ -2582,33 +2582,24 @@
     if (
-delegateResultSet
+priority
 Queue.is
@@ -2665,33 +2665,24 @@
 elegate(
-delegateResultSet
+priority
 Queue.pe
@@ -2746,103 +2746,35 @@
 : %7B%7D
+%22
 , 
-current result set hashcode: %7B%7D%22, delegateResultSetQueue.peek().row, getDelegate().hashCode()
+priorityQueue.peek().row
 );%0A 
@@ -2855,77 +2855,69 @@
 ass 
-ResultSetOrderByWrapper implements Comparable%3CResultSetOrderByWrapper
+ComparableResultSet implements Comparable%3CComparableResultSet
 %3E %7B%0A
@@ -3332,31 +3332,27 @@
 nal 
-ResultSetOrderByWrapper
+ComparableResultSet
  o) 

refactor StreamingOrderByReducerResultSet