/*
 * 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.nio.ByteBuffer;
import java.util.*;
import java.util.concurrent.atomic.*;
import java.util.function.*;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Iterables;

import org.apache.cassandra.config.*;
import org.apache.cassandra.cql3.*;
import org.apache.cassandra.cql3.statements.*;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.schema.*;
import org.apache.cassandra.utils.*;

/**
 * Helper methods to represent CFMetadata and related objects in CQL format
 */
public class ColumnFamilyStoreCQLHelper
{
    public static List<String> dumpReCreateStatements(CFMetaData metadata)
    {
        List<String> l = new ArrayList<>();
        // Types come first, as table can't be created without them
        l.addAll(ColumnFamilyStoreCQLHelper.getUserTypesAsCQL(metadata));
        // Record re-create schema statements
        l.add(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(metadata, true));
        // Dropped columns (and re-additions)
        l.addAll(ColumnFamilyStoreCQLHelper.getDroppedColumnsAsCQL(metadata));
        // Indexes applied as last, since otherwise they may interfere with column drops / re-additions
        l.addAll(ColumnFamilyStoreCQLHelper.getIndexesAsCQL(metadata));
        return l;
    }

    private static List<ColumnDefinition> getClusteringColumns(CFMetaData metadata)
    {
        List<ColumnDefinition> cds = new ArrayList<>(metadata.clusteringColumns().size());

        if (!metadata.isStaticCompactTable())
            for (ColumnDefinition cd : metadata.clusteringColumns())
                cds.add(cd);

        return cds;
    }

    private static List<ColumnDefinition> getPartitionColumns(CFMetaData metadata)
    {
        List<ColumnDefinition> cds = new ArrayList<>(metadata.partitionColumns().size());

        for (ColumnDefinition cd : metadata.partitionColumns().statics)
            cds.add(cd);

        if (metadata.isDense())
        {
            // remove an empty type
            for (ColumnDefinition cd : metadata.partitionColumns().withoutStatics())
                if (!cd.type.equals(EmptyType.instance))
                    cds.add(cd);
        }
        // "regular" columns are not exposed for static compact tables
        else if (!metadata.isStaticCompactTable())
        {
            for (ColumnDefinition cd : metadata.partitionColumns().withoutStatics())
                cds.add(cd);
        }

        return cds;
    }

    /**
     * Build a CQL String representation of Column Family Metadata
     */
    @VisibleForTesting
    public static String getCFMetadataAsCQL(CFMetaData metadata, boolean includeDroppedColumns)
    {
        StringBuilder sb = new StringBuilder();
        if (!isCqlCompatible(metadata))
        {
            sb.append(String.format("/*\nWarning: Table %s.%s omitted because it has constructs not compatible with CQL (was created via legacy API).\n",
                                    metadata.ksName,
                                    metadata.cfName));
            sb.append("\nApproximate structure, for reference:");
            sb.append("\n(this should not be used to reproduce this schema)\n\n");
        }

        sb.append("CREATE TABLE IF NOT EXISTS ");
        sb.append(quoteIdentifier(metadata.ksName)).append('.').append(quoteIdentifier(metadata.cfName)).append(" (");

        List<ColumnDefinition> partitionKeyColumns = metadata.partitionKeyColumns();
        List<ColumnDefinition> clusteringColumns = getClusteringColumns(metadata);
        List<ColumnDefinition> partitionColumns = getPartitionColumns(metadata);

        Consumer<StringBuilder> cdCommaAppender = commaAppender("\n\t");
        sb.append("\n\t");
        for (ColumnDefinition cfd: partitionKeyColumns)
        {
            cdCommaAppender.accept(sb);
            sb.append(toCQL(cfd));
            if (partitionKeyColumns.size() == 1 && clusteringColumns.size() == 0)
                sb.append(" PRIMARY KEY");
        }

        for (ColumnDefinition cfd: clusteringColumns)
        {
            cdCommaAppender.accept(sb);
            sb.append(toCQL(cfd));
        }

        for (ColumnDefinition cfd: partitionColumns)
        {
            cdCommaAppender.accept(sb);
            sb.append(toCQL(cfd, metadata.isStaticCompactTable()));
        }

        if (includeDroppedColumns)
        {
            for (Map.Entry<ByteBuffer, CFMetaData.DroppedColumn> entry: metadata.getDroppedColumns().entrySet())
            {
                if (metadata.getColumnDefinition(entry.getKey()) != null)
                    continue;

                CFMetaData.DroppedColumn droppedColumn = entry.getValue();
                cdCommaAppender.accept(sb);
                sb.append(quoteIdentifier(droppedColumn.name));
                sb.append(' ');
                sb.append(droppedColumn.type.asCQL3Type().toString());
            }
        }

        if (clusteringColumns.size() > 0 || partitionKeyColumns.size() > 1)
        {
            sb.append(",\n\tPRIMARY KEY (");
            if (partitionKeyColumns.size() > 1)
            {
                sb.append("(");
                Consumer<StringBuilder> pkCommaAppender = commaAppender(" ");
                for (ColumnDefinition cfd : partitionKeyColumns)
                {
                    pkCommaAppender.accept(sb);
                    sb.append(quoteIdentifier(cfd.name.toString()));
                }
                sb.append(")");
            }
            else
            {
                sb.append(quoteIdentifier(partitionKeyColumns.get(0).name.toString()));
            }

            for (ColumnDefinition cfd : metadata.clusteringColumns())
                sb.append(", ").append(quoteIdentifier(cfd.name.toString()));

            sb.append(')');
        }
        sb.append(")\n\t");
        sb.append("WITH ");

        sb.append("ID = ").append(metadata.cfId).append("\n\tAND ");

        if (metadata.isCompactTable())
            sb.append("COMPACT STORAGE\n\tAND ");

        if (clusteringColumns.size() > 0)
        {
            sb.append("CLUSTERING ORDER BY (");

            Consumer<StringBuilder> cOrderCommaAppender = commaAppender(" ");
            for (ColumnDefinition cd : clusteringColumns)
            {
                cOrderCommaAppender.accept(sb);
                sb.append(quoteIdentifier(cd.name.toString())).append(' ').append(cd.clusteringOrder().toString());
            }
            sb.append(")\n\tAND ");
        }

        sb.append(toCQL(metadata.params));
        sb.append(";");

        if (!isCqlCompatible(metadata))
        {
            sb.append("\n*/");
        }
        return sb.toString();
    }

    /**
     * Build a CQL String representation of User Types used in the given Column Family.
     *
     * Type order is ensured as types are built incrementally: from the innermost (most nested)
     * to the outermost.
     */
    @VisibleForTesting
    public static List<String> getUserTypesAsCQL(CFMetaData metadata)
    {
        List<UserType> types = new ArrayList<>();
        Set<UserType> typeSet = new HashSet<>();
        for (ColumnDefinition cd: Iterables.concat(metadata.partitionKeyColumns(), metadata.clusteringColumns(), metadata.partitionColumns()))
        {
            AbstractType type = cd.type;
            if (type instanceof UserType)
                resolveUserType((UserType) type, typeSet, types);
        }

        List<String> typeStrings = new ArrayList<>();
        for (UserType type: types)
            typeStrings.add(toCQL(type));
        return typeStrings;
    }

    /**
     * Build a CQL String representation of Dropped Columns in the given Column Family.
     *
     * If the column was dropped once, but is now re-created `ADD` will be appended accordingly.
     */
    @VisibleForTesting
    public static List<String> getDroppedColumnsAsCQL(CFMetaData metadata)
    {
        List<String> droppedColumns = new ArrayList<>();

        for (Map.Entry<ByteBuffer, CFMetaData.DroppedColumn> entry: metadata.getDroppedColumns().entrySet())
        {
            CFMetaData.DroppedColumn column = entry.getValue();
            droppedColumns.add(toCQLDrop(metadata.ksName, metadata.cfName, column));
            if (metadata.getColumnDefinition(entry.getKey()) != null)
                droppedColumns.add(toCQLAdd(metadata.ksName, metadata.cfName, metadata.getColumnDefinition(entry.getKey())));
        }

        return droppedColumns;
    }

    /**
     * Build a CQL String representation of Indexes on columns in the given Column Family
     */
    @VisibleForTesting
    public static List<String> getIndexesAsCQL(CFMetaData metadata)
    {
        List<String> indexes = new ArrayList<>();
        for (IndexMetadata indexMetadata: metadata.getIndexes())
            indexes.add(toCQL(metadata.ksName, metadata.cfName, indexMetadata));
        return indexes;
    }

    private static String toCQL(String keyspace, String cf, IndexMetadata indexMetadata)
    {
        if (indexMetadata.isCustom())
        {
            Map<String, String> options = new HashMap<>();
            indexMetadata.options.forEach((k, v) -> {
                if (!k.equals(IndexTarget.TARGET_OPTION_NAME) && !k.equals(IndexTarget.CUSTOM_INDEX_OPTION_NAME))
                    options.put(k, v);
            });

            return String.format("CREATE CUSTOM INDEX %s ON %s.%s (%s) USING '%s'%s;",
                                 quoteIdentifier(indexMetadata.name),
                                 quoteIdentifier(keyspace),
                                 quoteIdentifier(cf),
                                 indexMetadata.options.get(IndexTarget.TARGET_OPTION_NAME),
                                 indexMetadata.options.get(IndexTarget.CUSTOM_INDEX_OPTION_NAME),
                                 options.isEmpty() ? "" : " WITH OPTIONS " + toCQL(options));
        }
        else
        {
            return String.format("CREATE INDEX %s ON %s.%s (%s);",
                                 quoteIdentifier(indexMetadata.name),
                                 quoteIdentifier(keyspace),
                                 quoteIdentifier(cf),
                                 indexMetadata.options.get(IndexTarget.TARGET_OPTION_NAME));
        }
    }
    private static String toCQL(UserType userType)
    {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("CREATE TYPE %s.%s(",
                                quoteIdentifier(userType.keyspace),
                                quoteIdentifier(userType.getNameAsString())));

        Consumer<StringBuilder> commaAppender = commaAppender(" ");
        for (int i = 0; i < userType.size(); i++)
        {
            commaAppender.accept(sb);
            sb.append(String.format("%s %s",
                                    userType.fieldNameAsString(i),
                                    userType.fieldType(i).asCQL3Type()));
        }
        sb.append(");");
        return sb.toString();
    }

    private static String toCQL(TableParams tableParams)
    {
        StringBuilder builder = new StringBuilder();

        builder.append("bloom_filter_fp_chance = ").append(tableParams.bloomFilterFpChance);
        builder.append("\n\tAND dclocal_read_repair_chance = ").append(tableParams.dcLocalReadRepairChance);
        builder.append("\n\tAND crc_check_chance = ").append(tableParams.crcCheckChance);
        builder.append("\n\tAND default_time_to_live = ").append(tableParams.defaultTimeToLive);
        builder.append("\n\tAND gc_grace_seconds = ").append(tableParams.gcGraceSeconds);
        builder.append("\n\tAND min_index_interval = ").append(tableParams.minIndexInterval);
        builder.append("\n\tAND max_index_interval = ").append(tableParams.maxIndexInterval);
        builder.append("\n\tAND memtable_flush_period_in_ms = ").append(tableParams.memtableFlushPeriodInMs);
        builder.append("\n\tAND read_repair_chance = ").append(tableParams.readRepairChance);
        builder.append("\n\tAND speculative_retry = '").append(tableParams.speculativeRetry).append("'");
        builder.append("\n\tAND comment = ").append(singleQuote(tableParams.comment));
        builder.append("\n\tAND caching = ").append(toCQL(tableParams.caching.asMap()));
        builder.append("\n\tAND compaction = ").append(toCQL(tableParams.compaction.asMap()));
        builder.append("\n\tAND compression = ").append(toCQL(tableParams.compression.asMap()));

        builder.append("\n\tAND extensions = { ");
        for (Map.Entry<String, ByteBuffer> entry : tableParams.extensions.entrySet())
        {
            builder.append(singleQuote(entry.getKey()));
            builder.append(": ");
            builder.append("0x" + ByteBufferUtil.bytesToHex(entry.getValue()));
        }
        builder.append(" }");
        return builder.toString();
    }

    private static String toCQL(Map<?, ?> map)
    {
        StringBuilder builder = new StringBuilder("{ ");

        boolean isFirst = true;
        for (Map.Entry entry: map.entrySet())
        {
            if (isFirst)
                isFirst = false;
            else
                builder.append(", ");
            builder.append(singleQuote(entry.getKey().toString()));
            builder.append(": ");
            builder.append(singleQuote(entry.getValue().toString()));
        }

        builder.append(" }");
        return builder.toString();
    }

    private static String toCQL(ColumnDefinition cd)
    {
        return toCQL(cd, false);
    }

    private static String toCQL(ColumnDefinition cd, boolean isStaticCompactTable)
    {
        return String.format("%s %s%s",
                             quoteIdentifier(cd.name.toString()),
                             cd.type.asCQL3Type().toString(),
                             cd.isStatic() && !isStaticCompactTable ? " static" : "");
    }

    private static String toCQLAdd(String keyspace, String cf, ColumnDefinition cd)
    {
        return String.format("ALTER TABLE %s.%s ADD %s %s%s;",
                             quoteIdentifier(keyspace),
                             quoteIdentifier(cf),
                             quoteIdentifier(cd.name.toString()),
                             cd.type.asCQL3Type().toString(),
                             cd.isStatic() ? " static" : "");
    }

    private static String toCQLDrop(String keyspace, String cf, CFMetaData.DroppedColumn droppedColumn)
    {
        return String.format("ALTER TABLE %s.%s DROP %s USING TIMESTAMP %s;",
                             quoteIdentifier(keyspace),
                             quoteIdentifier(cf),
                             quoteIdentifier(droppedColumn.name),
                             droppedColumn.droppedTime);
    }

    private static void resolveUserType(UserType type, Set<UserType> typeSet, List<UserType> types)
    {
        for (AbstractType subType: type.fieldTypes())
            if (!typeSet.contains(subType) && subType instanceof UserType)
                resolveUserType((UserType) subType, typeSet, types);

        if (!typeSet.contains(type))
        {
            UserType t = type;
            typeSet.add(t);
            types.add(t);
        }
    }

    private static String singleQuote(String s)
    {
        return String.format("'%s'", s.replaceAll("'", "''"));
    }

    private static Consumer<StringBuilder> commaAppender(String afterComma)
    {
        AtomicBoolean isFirst = new AtomicBoolean(true);
        return new Consumer<StringBuilder>()
        {
            public void accept(StringBuilder stringBuilder)
            {
                if (!isFirst.getAndSet(false))
                    stringBuilder.append(',').append(afterComma);
            }
        };
    }

    private static String quoteIdentifier(String id)
    {
        return ColumnIdentifier.maybeQuote(id);
    }

    /**
     * Whether or not the given metadata is compatible / representable with CQL Language
     */
    public static boolean isCqlCompatible(CFMetaData metaData)
    {
        if (metaData.isSuper())
            return false;

        if (metaData.isCompactTable()
            && metaData.partitionColumns().withoutStatics().size() > 1
            && metaData.clusteringColumns().size() >= 1)
            return false;

        return true;
    }
}
