/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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.apache.cassandra.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.PeekingIterator;
import org.slf4j.Logger;

import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;


/**
 * Wrapper class for handling of multiple MerkleTrees at once.
 * 
 * The MerkleTree's are divided in Ranges of non-overlapping tokens.
 */
public class MerkleTrees implements Iterable<Map.Entry<Range<Token>, MerkleTree>>
{
    public static final MerkleTreesSerializer serializer = new MerkleTreesSerializer();

    private Map<Range<Token>, MerkleTree> merkleTrees = new TreeMap<>(new TokenRangeComparator());

    private IPartitioner partitioner;

    /**
     * Creates empty MerkleTrees object.
     * 
     * @param partitioner The partitioner to use
     */
    public MerkleTrees(IPartitioner partitioner)
    {
        this(partitioner, new ArrayList<>());
    }

    private MerkleTrees(IPartitioner partitioner, Collection<MerkleTree> merkleTrees)
    {
        this.partitioner = partitioner;
        addTrees(merkleTrees);
    }

    /**
     * Get the ranges that these merkle trees covers.
     * 
     * @return
     */
    public Collection<Range<Token>> ranges()
    {
        return merkleTrees.keySet();
    }

    /**
     * Get the partitioner in use.
     * 
     * @return
     */
    public IPartitioner partitioner()
    {
        return partitioner;
    }

    /**
     * Add merkle tree's with the defined maxsize and ranges.
     * 
     * @param maxsize
     * @param ranges
     */
    public void addMerkleTrees(int maxsize, Collection<Range<Token>> ranges)
    {
        for (Range<Token> range : ranges)
        {
            addMerkleTree(maxsize, range);
        }
    }

    /**
     * Add a MerkleTree with the defined size and range.
     * 
     * @param maxsize
     * @param range
     * @return The created merkle tree.
     */
    public MerkleTree addMerkleTree(int maxsize, Range<Token> range)
    {
        return addMerkleTree(maxsize, MerkleTree.RECOMMENDED_DEPTH, range);
    }

    @VisibleForTesting
    public MerkleTree addMerkleTree(int maxsize, byte hashdepth, Range<Token> range)
    {
        MerkleTree tree = new MerkleTree(partitioner, range, hashdepth, maxsize);
        addTree(tree);

        return tree;
    }

    /**
     * Get the MerkleTree.Range responsible for the given token.
     * 
     * @param t
     * @return
     */
    @VisibleForTesting
    public MerkleTree.TreeRange get(Token t)
    {
        return getMerkleTree(t).get(t);
    }

    /**
     * Init all MerkleTree's with an even tree distribution.
     */
    public void init()
    {
        for (Range<Token> range : merkleTrees.keySet())
        {
            init(range);
        }
    }

    /**
     * Init a selected MerkleTree with an even tree distribution.
     * 
     * @param range
     */
    public void init(Range<Token> range)
    {
        merkleTrees.get(range).init();
    }

    /**
     * Split the MerkleTree responsible for the given token.
     * 
     * @param t
     * @return
     */
    public boolean split(Token t)
    {
        return getMerkleTree(t).split(t);
    }

    /**
     * Invalidate the MerkleTree responsible for the given token.
     * 
     * @param t
     */
    @VisibleForTesting
    public void invalidate(Token t)
    {
        getMerkleTree(t).invalidate(t);
    }

    /**
     * Get the MerkleTree responsible for the given token range.
     * 
     * @param range
     * @return
     */
    public MerkleTree getMerkleTree(Range<Token> range)
    {
        return merkleTrees.get(range);
    }

    public long size()
    {
        long size = 0;

        for (MerkleTree tree : merkleTrees.values())
        {
            size += tree.size();
        }

        return size;
    }

    @VisibleForTesting
    public void maxsize(Range<Token> range, int maxsize)
    {
        getMerkleTree(range).maxsize(maxsize);
    }

    /**
     * Get the MerkleTree responsible for the given token.
     * 
     * @param t
     * @return The given MerkleTree or null if none exist.
     */
    private MerkleTree getMerkleTree(Token t)
    {
        for (Range<Token> range : merkleTrees.keySet())
        {
            if (range.contains(t))
                return merkleTrees.get(range);
        }

        throw new AssertionError("Expected tree for token " + t);
    }

    private void addTrees(Collection<MerkleTree> trees)
    {
        for (MerkleTree tree : trees)
        {
            addTree(tree);
        }
    }

    private void addTree(MerkleTree tree)
    {
        assert validateNonOverlapping(tree) : "Range [" + tree.fullRange + "] is intersecting an existing range";

        merkleTrees.put(tree.fullRange, tree);
    }

    private boolean validateNonOverlapping(MerkleTree tree)
    {
        for (Range<Token> range : merkleTrees.keySet())
        {
            if (tree.fullRange.intersects(range))
                return false;
        }

        return true;
    }

    /**
     * Get an iterator for all the invalids generated by the MerkleTrees.
     * 
     * @return
     */
    public TreeRangeIterator invalids()
    {
        return new TreeRangeIterator();
    }

    /**
     * Log the row count per leaf for all MerkleTrees.
     * 
     * @param logger
     */
    public void logRowCountPerLeaf(Logger logger)
    {
        for (MerkleTree tree : merkleTrees.values())
        {
            tree.histogramOfRowCountPerLeaf().log(logger);
        }
    }

    /**
     * Log the row size per leaf for all MerkleTrees.
     * 
     * @param logger
     */
    public void logRowSizePerLeaf(Logger logger)
    {
        for (MerkleTree tree : merkleTrees.values())
        {
            tree.histogramOfRowSizePerLeaf().log(logger);
        }
    }

    @VisibleForTesting
    public byte[] hash(Range<Token> range)
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        boolean hashed = false;

        try
        {
            for (Range<Token> rt : merkleTrees.keySet())
            {
                if (rt.intersects(range))
                {
                    byte[] bytes = merkleTrees.get(rt).hash(range);
                    if (bytes != null)
                    {
                        baos.write(bytes);
                        hashed = true;
                    }
                }
            }
        }
        catch (IOException e)
        {
            throw new RuntimeException("Unable to append merkle tree hash to result");
        }
        
        return hashed ? baos.toByteArray() : null;
    }

    /**
     * Get an iterator of all ranges and their MerkleTrees.
     */
    public Iterator<Map.Entry<Range<Token>, MerkleTree>> iterator()
    {
        return merkleTrees.entrySet().iterator();
    }

    public long rowCount()
    {
        long totalCount = 0;
        for (MerkleTree tree : merkleTrees.values())
        {
            totalCount += tree.rowCount();
        }
        return totalCount;
    }

    public class TreeRangeIterator extends AbstractIterator<MerkleTree.TreeRange> implements
            Iterable<MerkleTree.TreeRange>,
            PeekingIterator<MerkleTree.TreeRange>
    {
        private final Iterator<MerkleTree> it;

        private MerkleTree.TreeRangeIterator current = null;

        private TreeRangeIterator()
        {
            it = merkleTrees.values().iterator();
        }

        public MerkleTree.TreeRange computeNext()
        {
            if (current == null || !current.hasNext())
                return nextIterator();

            return current.next();
        }

        private MerkleTree.TreeRange nextIterator()
        {
            if (it.hasNext())
            {
                current = it.next().invalids();

                return current.next();
            }

            return endOfData();
        }

        public Iterator<MerkleTree.TreeRange> iterator()
        {
            return this;
        }
    }

    /**
     * Get the differences between the two sets of MerkleTrees.
     * 
     * @param ltree
     * @param rtree
     * @return
     */
    public static List<Range<Token>> difference(MerkleTrees ltree, MerkleTrees rtree)
    {
        List<Range<Token>> differences = new ArrayList<>();
        for (MerkleTree tree : ltree.merkleTrees.values())
        {
            differences.addAll(MerkleTree.difference(tree, rtree.getMerkleTree(tree.fullRange)));
        }
        return differences;
    }

    public static class MerkleTreesSerializer implements IVersionedSerializer<MerkleTrees>
    {
        public void serialize(MerkleTrees trees, DataOutputPlus out, int version) throws IOException
        {
            out.writeInt(trees.merkleTrees.size());
            for (MerkleTree tree : trees.merkleTrees.values())
            {
                MerkleTree.serializer.serialize(tree, out, version);
            }
        }

        public MerkleTrees deserialize(DataInputPlus in, int version) throws IOException
        {
            IPartitioner partitioner = null;
            int nTrees = in.readInt();
            Collection<MerkleTree> trees = new ArrayList<>(nTrees);
            if (nTrees > 0)
            {
                for (int i = 0; i < nTrees; i++)
                {
                    MerkleTree tree = MerkleTree.serializer.deserialize(in, version);
                    trees.add(tree);

                    if (partitioner == null)
                        partitioner = tree.partitioner();
                    else
                        assert tree.partitioner() == partitioner;
                }
            }

            return new MerkleTrees(partitioner, trees);
        }

        public long serializedSize(MerkleTrees trees, int version)
        {
            assert trees != null;

            long size = TypeSizes.sizeof(trees.merkleTrees.size());
            for (MerkleTree tree : trees.merkleTrees.values())
            {
                size += MerkleTree.serializer.serializedSize(tree, version);
            }
            return size;
        }

    }

    private static class TokenRangeComparator implements Comparator<Range<Token>>
    {
        @Override
        public int compare(Range<Token> rt1, Range<Token> rt2)
        {
            if (rt1.left.compareTo(rt2.left) == 0)
                return 0;

            return rt1.compareTo(rt2);
        }
    }
}
