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

import java.net.InetAddress;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cassandra.auth.Permission;
import org.apache.cassandra.config.*;
import org.apache.cassandra.cql3.CFName;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.BytesType;
import org.apache.cassandra.db.marshal.EmptyType;
import org.apache.cassandra.db.view.View;
import org.apache.cassandra.exceptions.*;
import org.apache.cassandra.gms.ApplicationState;
import org.apache.cassandra.gms.Gossiper;
import org.apache.cassandra.io.sstable.format.VersionAndType;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.schema.IndexMetadata;
import org.apache.cassandra.schema.Indexes;
import org.apache.cassandra.schema.TableParams;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.MigrationManager;
import org.apache.cassandra.service.QueryState;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.transport.Event;
import org.apache.cassandra.utils.NoSpamLogger;

import static java.lang.String.format;
import static org.apache.cassandra.thrift.ThriftValidation.validateColumnFamily;

public class AlterTableStatement extends SchemaAlteringStatement
{
    private static final Logger logger = LoggerFactory.getLogger(AlterTableStatement.class);
    private static final NoSpamLogger noSpamLogger = NoSpamLogger.getLogger(logger, 5L, TimeUnit.MINUTES);

    public enum Type
    {
        ADD, ALTER, DROP, DROP_COMPACT_STORAGE, OPTS, RENAME
    }

    public final Type oType;
    public final CQL3Type.Raw validator;
    public final ColumnIdentifier.Raw rawColumnName;
    private final TableAttributes attrs;
    private final Map<ColumnIdentifier.Raw, ColumnIdentifier> renames;
    private final boolean isStatic; // Only for ALTER ADD
    private final Long deleteTimestamp;

    public AlterTableStatement(CFName name,
                               Type type,
                               ColumnIdentifier.Raw columnName,
                               CQL3Type.Raw validator,
                               TableAttributes attrs,
                               Map<ColumnIdentifier.Raw, ColumnIdentifier> renames,
                               boolean isStatic,
                               Long deleteTimestamp)
    {
        super(name);
        this.oType = type;
        this.rawColumnName = columnName;
        this.validator = validator; // used only for ADD/ALTER commands
        this.attrs = attrs;
        this.renames = renames;
        this.isStatic = isStatic;
        this.deleteTimestamp = deleteTimestamp;
    }

    public void checkAccess(ClientState state) throws UnauthorizedException, InvalidRequestException
    {
        state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.ALTER);
    }

    public void validate(ClientState state)
    {
        // validated in announceMigration()
    }

    public Event.SchemaChange announceMigration(QueryState queryState, boolean isLocalOnly) throws RequestValidationException
    {
        CFMetaData meta = validateColumnFamily(keyspace(), columnFamily());
        if (meta.isView())
            throw new InvalidRequestException("Cannot use ALTER TABLE on Materialized View");

        CFMetaData cfm;

        CQL3Type validator = this.validator == null ? null : this.validator.prepare(keyspace());
        ColumnIdentifier columnName = null;
        ColumnDefinition def = null;
        if (rawColumnName != null)
        {
            columnName = rawColumnName.prepare(meta);
            def = meta.getColumnDefinition(columnName);
        }

        List<ViewDefinition> viewUpdates = null;
        Iterable<ViewDefinition> views = View.findAll(keyspace(), columnFamily());

        switch (oType)
        {
            case ALTER:
                // We do not support altering of types and only allow this to for people who have already one
                // through the upgrade of 2.x CQL-created SSTables with Thrift writes, affected by CASSANDRA-15778.
                if (meta.isDense()
                    && meta.compactValueColumn().equals(def)
                    && meta.compactValueColumn().type instanceof EmptyType
                    && validator != null)
                {
                    if (validator.getType() instanceof BytesType)
                    {
                        cfm = meta.copyWithNewCompactValueType(validator.getType());
                        break;
                    }

                    throw new InvalidRequestException(String.format("Compact value type can only be changed to BytesType, but %s was given.",
                                                                    validator.getType()));
                }
                else
                {
                    throw new InvalidRequestException("Altering of types is not allowed");
                }
            case ADD:
                assert columnName != null;
                if (meta.isCompactTable())
                    throw new InvalidRequestException("Cannot add new column to a COMPACT STORAGE table");

                cfm = meta.copy();

                if (isStatic)
                {
                    if (!cfm.isCompound())
                        throw new InvalidRequestException("Static columns are not allowed in COMPACT STORAGE tables");
                    if (cfm.clusteringColumns().isEmpty())
                        throw new InvalidRequestException("Static columns are only useful (and thus allowed) if the table has at least one clustering column");
                }

                if (def != null)
                {
                    switch (def.kind)
                    {
                        case PARTITION_KEY:
                        case CLUSTERING:
                            throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with a PRIMARY KEY part", columnName));
                        default:
                            throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with an existing column", columnName));
                    }
                }

                AbstractType<?> type = validator.getType();
                if (type.isCollection() && type.isMultiCell())
                {
                    if (!cfm.isCompound())
                        throw new InvalidRequestException("Cannot use non-frozen collections in COMPACT STORAGE tables");
                    if (cfm.isSuper())
                        throw new InvalidRequestException("Cannot use non-frozen collections with super column families");
                }

                ColumnDefinition toAdd = isStatic
                                       ? ColumnDefinition.staticDef(cfm, columnName.bytes, type)
                                       : ColumnDefinition.regularDef(cfm, columnName.bytes, type);

                CFMetaData.DroppedColumn droppedColumn = meta.getDroppedColumns().get(columnName.bytes);
                if (null != droppedColumn)
                {
                    if (droppedColumn.kind != toAdd.kind)
                    {
                        String message =
                            String.format("Cannot re-add previously dropped column '%s' of kind %s, incompatible with previous kind %s",
                                          columnName,
                                          toAdd.kind,
                                          droppedColumn.kind == null ? "UNKNOWN" : droppedColumn.kind);
                        throw new InvalidRequestException(message);
                    }

                    // After #8099, not safe to re-add columns of incompatible types - until *maybe* deser logic with dropped
                    // columns is pushed deeper down the line. The latter would still be problematic in cases of schema races.
                    if (!type.isValueCompatibleWith(droppedColumn.type))
                    {
                        String message =
                            String.format("Cannot re-add previously dropped column '%s' of type %s, incompatible with previous type %s",
                                          columnName,
                                          type.asCQL3Type(),
                                          droppedColumn.type.asCQL3Type());
                        throw new InvalidRequestException(message);
                    }

                    // Cannot re-add a dropped counter column. See #7831.
                    if (meta.isCounter())
                        throw new InvalidRequestException(String.format("Cannot re-add previously dropped counter column %s", columnName));
                }

                cfm.addColumnDefinition(toAdd);

                // Adding a column to a table which has an include all view requires the column to be added to the view as well
                if (!isStatic)
                {
                    for (ViewDefinition view : views)
                    {
                        if (view.includeAllColumns)
                        {
                            ViewDefinition viewCopy = view.copy();
                            viewCopy.metadata.addColumnDefinition(ColumnDefinition.regularDef(viewCopy.metadata, columnName.bytes, type));
                            if (viewUpdates == null)
                                viewUpdates = new ArrayList<>();
                            viewUpdates.add(viewCopy);
                        }
                    }
                }
                break;

            case DROP:
                assert columnName != null;
                if (!meta.isCQLTable())
                    throw new InvalidRequestException("Cannot drop columns from a non-CQL3 table");

                if (def == null)
                    throw new InvalidRequestException(String.format("Column %s was not found in table %s", columnName, columnFamily()));

                cfm = meta.copy();

                switch (def.kind)
                {
                    case PARTITION_KEY:
                    case CLUSTERING:
                        throw new InvalidRequestException(String.format("Cannot drop PRIMARY KEY part %s", columnName));
                    case REGULAR:
                    case STATIC:
                        ColumnDefinition toDelete = null;
                        for (ColumnDefinition columnDef : cfm.partitionColumns())
                        {
                            if (columnDef.name.equals(columnName))
                            {
                                toDelete = columnDef;
                                break;
                            }
                        }
                        assert toDelete != null;
                        cfm.removeColumnDefinition(toDelete);
                        cfm.recordColumnDrop(toDelete, deleteTimestamp == null ? queryState.getTimestamp() : deleteTimestamp);
                        break;
                }

                // If the dropped column is required by any secondary indexes
                // we reject the operation, as the indexes must be dropped first
                Indexes allIndexes = cfm.getIndexes();
                if (!allIndexes.isEmpty())
                {
                    ColumnFamilyStore store = Keyspace.openAndGetStore(cfm);
                    Set<IndexMetadata> dependentIndexes = store.indexManager.getDependentIndexes(def);
                    if (!dependentIndexes.isEmpty())
                        throw new InvalidRequestException(String.format("Cannot drop column %s because it has " +
                                                                        "dependent secondary indexes (%s)",
                                                                        def,
                                                                        dependentIndexes.stream()
                                                                                        .map(i -> i.name)
                                                                                        .collect(Collectors.joining(","))));
                }

                if (!Iterables.isEmpty(views))
                    throw new InvalidRequestException(String.format("Cannot drop column %s on base table %s with materialized views.",
                                                                    columnName.toString(),
                                                                    columnFamily()));
                break;
            case DROP_COMPACT_STORAGE:

                if (!DatabaseDescriptor.enableDropCompactStorage())
                    throw new InvalidRequestException("DROP COMPACT STORAGE is disabled. Enable in cassandra.yaml to use.");

                if (!meta.isCompactTable())
                    throw new InvalidRequestException("Cannot DROP COMPACT STORAGE on table without COMPACT STORAGE");

                validateCanDropCompactStorage();

                cfm = meta.asNonCompact();
                break;
            case OPTS:
                if (attrs == null)
                    throw new InvalidRequestException("ALTER TABLE WITH invoked, but no parameters found");
                attrs.validate();

                cfm = meta.copy();

                TableParams params = attrs.asAlteredTableParams(cfm.params);

                if (!Iterables.isEmpty(views) && params.gcGraceSeconds == 0)
                {
                    throw new InvalidRequestException("Cannot alter gc_grace_seconds of the base table of a " +
                                                      "materialized view to 0, since this value is used to TTL " +
                                                      "undelivered updates. Setting gc_grace_seconds too low might " +
                                                      "cause undelivered updates to expire " +
                                                      "before being replayed.");
                }

                if (meta.isCounter() && params.defaultTimeToLive > 0)
                    throw new InvalidRequestException("Cannot set default_time_to_live on a table with counters");

                cfm.params(params);

                break;
            case RENAME:
                cfm = meta.copy();

                for (Map.Entry<ColumnIdentifier.Raw, ColumnIdentifier> entry : renames.entrySet())
                {
                    ColumnIdentifier from = entry.getKey().prepare(cfm);
                    ColumnIdentifier to = entry.getValue();

                    cfm.renameColumn(from, to);

                    // If the view includes a renamed column, it must be renamed in the view table and the definition.
                    for (ViewDefinition view : views)
                    {
                        if (!view.includes(from)) continue;

                        ViewDefinition viewCopy = view.copy();
                        ColumnIdentifier viewFrom = entry.getKey().prepare(viewCopy.metadata);
                        ColumnIdentifier viewTo = entry.getValue();
                        viewCopy.renameColumn(viewFrom, viewTo);

                        if (viewUpdates == null)
                            viewUpdates = new ArrayList<>();
                        viewUpdates.add(viewCopy);
                    }
                }
                break;
            default:
                throw new InvalidRequestException("Can not alter table: unknown option type " + oType);
        }

        MigrationManager.announceColumnFamilyUpdate(cfm, viewUpdates, isLocalOnly);
        return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
    }

    /**
     * Throws if DROP COMPACT STORAGE cannot be used (yet) because the cluster is not sufficiently upgraded. To be able
     * to use DROP COMPACT STORAGE, we need to ensure that no pre-3.0 sstables exists in the cluster, as we won't be
     * able to read them anymore once COMPACT STORAGE is dropped (see CASSANDRA-15897). In practice, this method checks
     * 3 things:
     *   1) that all nodes are on 3.0+. We need this because 2.x nodes don't advertise their sstable versions.
     *   2) for 3.0+, we use the new (CASSANDRA-15897) sstables versions set gossiped by all nodes to ensure all
     *      sstables have been upgraded cluster-wise.
     *   3) if the cluster still has some 3.0 nodes that predate CASSANDRA-15897, we will not have the sstable versions
     *      for them. In that case, we also refuse DROP COMPACT (even though it may well be safe at this point) and ask
     *      the user to upgrade all nodes.
     */
    private void validateCanDropCompactStorage()
    {
        Set<InetAddress> before3 = new HashSet<>();
        Set<InetAddress> preC15897nodes = new HashSet<>();
        Set<InetAddress> with2xSStables = new HashSet<>();
        Splitter onComma = Splitter.on(',').omitEmptyStrings().trimResults();
        for (InetAddress node : StorageService.instance.getTokenMetadata().getAllEndpoints())
        {
            if (MessagingService.instance().getVersion(node) < MessagingService.VERSION_30)
            {
                before3.add(node);
                continue;
            }

            String sstableVersionsString = Gossiper.instance.getApplicationState(node, ApplicationState.SSTABLE_VERSIONS);
            if (sstableVersionsString == null)
            {
                preC15897nodes.add(node);
                continue;
            }

            try
            {
                // Note: 'storeRows' is basically a marker for 3.0+ sstables.
                boolean has2xSStables = onComma.splitToList(sstableVersionsString)
                                               .stream()
                                               .map(VersionAndType::fromString)
                                               .anyMatch(v -> !v.version().storeRows());
                if (has2xSStables)
                    with2xSStables.add(node);
            }
            catch (IllegalArgumentException e)
            {
                // Means VersionType::fromString didn't parse a version correctly. Which shouldn't happen, we shouldn't
                // have garbage in Gossip. But crashing the request is not ideal, so we log the error but ignore the
                // node otherwise.
                noSpamLogger.error("Unexpected error parsing sstable versions from gossip for {} (gossiped value " +
                                   "is '{}'). This is a bug and should be reported. Cannot ensure that {} has no " +
                                   "non-upgraded 2.x sstables anymore. If after this DROP COMPACT STORAGE some old " +
                                   "sstables cannot be read anymore, please use `upgradesstables` with the " +
                                   "`--force-compact-storage-on` option.", node, sstableVersionsString, node);
            }
        }

        if (!before3.isEmpty())
            throw new InvalidRequestException(format("Cannot DROP COMPACT STORAGE as some nodes in the cluster (%s) " +
                                                     "are not on 3.0+ yet. Please upgrade those nodes and run " +
                                                     "`upgradesstables` before retrying.", before3));
        if (!preC15897nodes.isEmpty())
            throw new InvalidRequestException(format("Cannot guarantee that DROP COMPACT STORAGE is safe as some nodes " +
                                                     "in the cluster (%s) do not have https://issues.apache.org/jira/browse/CASSANDRA-15897. " +
                                                     "Please upgrade those nodes and retry.", preC15897nodes));
        if (!with2xSStables.isEmpty())
            throw new InvalidRequestException(format("Cannot DROP COMPACT STORAGE as some nodes in the cluster (%s) " +
                                                     "has some non-upgraded 2.x sstables. Please run `upgradesstables` " +
                                                     "on those nodes before retrying", with2xSStables));
    }

    public String toString()
    {
        return String.format("AlterTableStatement(name=%s, type=%s, column=%s, validator=%s)",
                             cfName,
                             oType,
                             rawColumnName,
                             validator);
    }
}
