/**
 * Copyright (C) 2009-2013 FoundationDB, LLC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.foundationdb.server.store.statistics;

import com.foundationdb.ais.model.IndexColumn;
import com.foundationdb.server.service.session.Session;
import com.foundationdb.server.service.tree.KeyCreator;
import com.foundationdb.server.store.statistics.histograms.Sampler;
import com.persistit.Key;

import java.util.Map;
import java.util.TreeMap;

public class FDBSingleColumnIndexStatisticsVisitor extends IndexStatisticsGenerator<Key,byte[]>
{
    private final Map<Key,int[]> countMap = new TreeMap<>(); // Is ordered required?
    private final int field;

    public FDBSingleColumnIndexStatisticsVisitor(KeyCreator keyCreator, IndexColumn indexColumn)
    {
        super(new PersistitKeyFlywheel(keyCreator), indexColumn.getIndex(), 1, indexColumn.getPosition());
        this.field = indexColumn.getPosition();
    }


    @Override
    public void init(int bucketCount, long distinctCount) {
        // TODO: can't call super?
        //super.init(bucketCount, distinctCount);
    }

    @Override
    public void finish(int bucketCount) {
        // TODO: Why init here?
        super.init(bucketCount, rowCount);
        try {
            for(Map.Entry<Key,int[]> entry : countMap.entrySet()) {
                int keyCount = entry.getValue()[0];
                for(int i = 0; i < keyCount; ++i) {
                    loadKey(entry.getKey());
                }
            }
        } finally {
            super.finish(bucketCount);
        }
    }

    @Override
    public void visit(Key key, byte[] value) {
        key.indexTo(field);
        int[] curCount = countMap.get(key);
        if(curCount == null) {
            Key storedKey = new Key(null, key.getEncodedSize());
            key.copyTo(storedKey);
            curCount = new int[1];
            countMap.put(storedKey, curCount);
        }
        curCount[0] += 1;
        rowCount++;
    }

    @Override
    public Sampler<Key> createKeySampler(int bucketCount, long distinctCount) {
        return new Sampler<>(
                new PersistitKeySplitter(columnCount(), getKeysFlywheel()),
                bucketCount,
                distinctCount,
                getKeysFlywheel()
        );
    }

    @Override
    protected byte[] copyOfKeyBytes(Key key) {
        byte[] copy = new byte[key.getEncodedSize()];
        System.arraycopy(key.getEncodedBytes(), 0, copy, 0, copy.length);
        return copy;
    }
}

@@ -1168,16 +1168,86 @@
 te%5B%5D%3E%0A%7B%0A
+    private final Key extractKey = new Key(null, Key.MAX_KEY_LENGTH);%0A
     priv
@@ -1708,31 +1708,60 @@
  // 
-TODO: can't call super?
+Does not do generator init until finish because just
 %0A   
@@ -1771,47 +1771,39 @@
   //
-sup
+ buff
 er
-.
 in
-it(bucketCount, distinctCount);
+g counts in this pass.
 %0A   
@@ -1877,28 +1877,65 @@
  // 
-TODO: Why
+Now
  init 
+t
 he
-re?
+ generator and replay the accumulated counts.
 %0A   
@@ -2402,16 +2402,66 @@
 field);%0A
+        extractKey.clear().appendKeySegment(key);%0A
         
@@ -2490,17 +2490,24 @@
 Map.get(
-k
+extractK
 ey);%0A   
@@ -2574,66 +2574,15 @@
 Key(
-null, key.getEncodedSize());%0A            key.copyTo(stored
+extract
 Key)

Fix counting of single column keys to actually isolate the one key it wants.