/*
* 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.db;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import org.junit.BeforeClass;
import org.junit.Test;

import org.apache.cassandra.db.rows.UnfilteredRowIterator;
import org.apache.cassandra.schema.ColumnMetadata;
import org.apache.cassandra.db.rows.EncodingStats;
import org.apache.cassandra.db.rows.UnfilteredRowIterators;
import org.apache.cassandra.db.marshal.AsciiType;
import org.apache.cassandra.db.partitions.*;
import org.apache.cassandra.io.util.DataInputBuffer;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.Util;
import org.apache.cassandra.schema.KeyspaceParams;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

public class PartitionTest
{
    private static final String KEYSPACE1 = "Keyspace1";
    private static final String CF_STANDARD1 = "Standard1";
    private static final String CF_TENCOL = "TenColumns";

    @BeforeClass
    public static void defineSchema() throws ConfigurationException
    {
        SchemaLoader.prepareServer();
        SchemaLoader.createKeyspace(KEYSPACE1,
                                    KeyspaceParams.simple(1),
                                    SchemaLoader.standardCFMD(KEYSPACE1, CF_STANDARD1),
                                    SchemaLoader.standardCFMD(KEYSPACE1, CF_TENCOL, 10, AsciiType.instance));
    }

    @Test
    public void testSingleColumn() throws IOException
    {
        ColumnFamilyStore cfs = Keyspace.open(KEYSPACE1).getColumnFamilyStore(CF_STANDARD1);
        PartitionUpdate update = new RowUpdateBuilder(cfs.metadata(), 5, "key1")
                                 .clustering("c")
                                 .add("val", "val1")
                                 .buildUpdate();

        CachedBTreePartition partition = CachedBTreePartition.create(update.unfilteredIterator(), FBUtilities.nowInSeconds());

        DataOutputBuffer bufOut = new DataOutputBuffer();
        CachedPartition.cacheSerializer.serialize(partition, bufOut);

        CachedPartition deserialized = CachedPartition.cacheSerializer.deserialize(new DataInputBuffer(bufOut.getData()));

        assert deserialized != null;
        assert deserialized.metadata().name.equals(CF_STANDARD1);
        assert deserialized.partitionKey().equals(partition.partitionKey());
    }

    @Test
    public void testManyColumns() throws IOException
    {
        ColumnFamilyStore cfs = Keyspace.open(KEYSPACE1).getColumnFamilyStore(CF_TENCOL);
        RowUpdateBuilder builder = new RowUpdateBuilder(cfs.metadata(), 5, "key1")
                                   .clustering("c")
                                   .add("val", "val1");

        for (int i = 0; i < 10; i++)
            builder.add("val" + i, "val" + i);

        PartitionUpdate update = builder.buildUpdate();

        CachedBTreePartition partition = CachedBTreePartition.create(update.unfilteredIterator(), FBUtilities.nowInSeconds());

        DataOutputBuffer bufOut = new DataOutputBuffer();
        CachedPartition.cacheSerializer.serialize(partition, bufOut);

        CachedPartition deserialized = CachedPartition.cacheSerializer.deserialize(new DataInputBuffer(bufOut.getData()));

        assertEquals(partition.columns().regulars.size(), deserialized.columns().regulars.size());
        assertEquals(deserialized.columns().regulars.getSimple(1), partition.columns().regulars.getSimple(1));
        assertEquals(deserialized.columns().regulars.getSimple(5), partition.columns().regulars.getSimple(5));

        ColumnMetadata cDef = cfs.metadata().getColumn(ByteBufferUtil.bytes("val8"));
        assertEquals(partition.lastRow().getCell(cDef).buffer(), deserialized.lastRow().getCell(cDef).buffer());
        assert deserialized.partitionKey().equals(partition.partitionKey());
    }

    @Test
    public void testDigest() throws NoSuchAlgorithmException
    {
        testDigest(MessagingService.current_version);
    }

    public void testDigest(int version) throws NoSuchAlgorithmException
    {
        ColumnFamilyStore cfs = Keyspace.open(KEYSPACE1).getColumnFamilyStore(CF_TENCOL);

        try
        {
            RowUpdateBuilder builder = new RowUpdateBuilder(cfs.metadata(), 5, "key1").clustering("c").add("val", "val1");
            for (int i = 0; i < 10; i++)
                builder.add("val" + i, "val" + i);
            builder.build().applyUnsafe();

            new RowUpdateBuilder(cfs.metadata(), 5, "key2").clustering("c").add("val", "val2").build().applyUnsafe();

            ReadCommand cmd1 = Util.cmd(cfs, "key1").build();
            ReadCommand cmd2 = Util.cmd(cfs, "key2").build();
            ImmutableBTreePartition p1 = Util.getOnlyPartitionUnfiltered(cmd1);
            ImmutableBTreePartition p2 = Util.getOnlyPartitionUnfiltered(cmd2);

            byte[] digest1 = getDigest(p1.unfilteredIterator(), version);
            byte[] digest2 = getDigest(p2.unfilteredIterator(), version);
            assertFalse(Arrays.equals(digest1, digest2));

            p1 = Util.getOnlyPartitionUnfiltered(Util.cmd(cfs, "key2").build());
            p2 = Util.getOnlyPartitionUnfiltered(Util.cmd(cfs, "key2").build());
            digest1 = getDigest(p1.unfilteredIterator(), version);
            digest2 = getDigest(p2.unfilteredIterator(), version);
            assertArrayEquals(digest1, digest2);

            p1 = Util.getOnlyPartitionUnfiltered(Util.cmd(cfs, "key2").build());
            RowUpdateBuilder.deleteRow(cfs.metadata(), 6, "key2", "c").applyUnsafe();
            p2 = Util.getOnlyPartitionUnfiltered(Util.cmd(cfs, "key2").build());
            digest1 = getDigest(p1.unfilteredIterator(), version);
            digest2 = getDigest(p2.unfilteredIterator(), version);
            assertFalse(Arrays.equals(digest1, digest2));
        }
        finally
        {
            cfs.truncateBlocking();
        }
    }

    private byte[] getDigest(UnfilteredRowIterator partition, int version)
    {
        Digest digest = Digest.forReadResponse();
        UnfilteredRowIterators.digest(partition, digest, version);
        return digest.digest();
    }

    @Test
    public void testColumnStatsRecordsRowDeletesCorrectly()
    {
        long timestamp = System.currentTimeMillis();
        int localDeletionTime = (int) (timestamp / 1000);

        ColumnFamilyStore cfs = Keyspace.open(KEYSPACE1).getColumnFamilyStore(CF_TENCOL);
        RowUpdateBuilder builder = new RowUpdateBuilder(cfs.metadata(), 5, "key1").clustering("c").add("val", "val1");
        for (int i = 0; i < 10; i++)
            builder.add("val" + i, "val" + i);
        builder.build().applyUnsafe();

        RowUpdateBuilder.deleteRowAt(cfs.metadata(), 10L, localDeletionTime, "key1", "c").applyUnsafe();
        ImmutableBTreePartition partition = Util.getOnlyPartitionUnfiltered(Util.cmd(cfs, "key1").build());
        EncodingStats stats = partition.stats();
        assertEquals(localDeletionTime, stats.minLocalDeletionTime);
    }
}
