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

import com.google.common.base.Optional;
import com.google.common.base.Strings;
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.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.cql3.CFName;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.cql3.IndexName;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.exceptions.RequestValidationException;
import org.apache.cassandra.exceptions.UnauthorizedException;
import org.apache.cassandra.schema.IndexMetadata;
import org.apache.cassandra.schema.Indexes;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.MigrationManager;
import org.apache.cassandra.thrift.ThriftValidation;
import org.apache.cassandra.transport.Event;

/** A <code>CREATE INDEX</code> statement parsed from a CQL query. */
public class CreateIndexStatement extends SchemaAlteringStatement
{
    private static final Logger logger = LoggerFactory.getLogger(CreateIndexStatement.class);

    private final String indexName;
    private final List<IndexTarget.Raw> rawTargets;
    private final IndexPropDefs properties;
    private final boolean ifNotExists;

    public CreateIndexStatement(CFName name,
                                IndexName indexName,
                                List<IndexTarget.Raw> targets,
                                IndexPropDefs properties,
                                boolean ifNotExists)
    {
        super(name);
        this.indexName = indexName.getIdx();
        this.rawTargets = targets;
        this.properties = properties;
        this.ifNotExists = ifNotExists;
    }

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

    public void validate(ClientState state) throws RequestValidationException
    {
        CFMetaData cfm = ThriftValidation.validateColumnFamily(keyspace(), columnFamily());

        if (cfm.isCounter())
            throw new InvalidRequestException("Secondary indexes are not supported on counter tables");

        if (cfm.isView())
            throw new InvalidRequestException("Secondary indexes are not supported on materialized views");

        if (cfm.isCompactTable() && !cfm.isStaticCompactTable())
            throw new InvalidRequestException("Secondary indexes are not supported on COMPACT STORAGE tables that have clustering columns");

        List<IndexTarget> targets = new ArrayList<>(rawTargets.size());
        for (IndexTarget.Raw rawTarget : rawTargets)
            targets.add(rawTarget.prepare(cfm));

        if (targets.isEmpty() && !properties.isCustom)
            throw new InvalidRequestException("Only CUSTOM indexes can be created without specifying a target column");

        if (targets.size() > 1)
            validateTargetsForMultiColumnIndex(targets);

        for (IndexTarget target : targets)
        {
            ColumnDefinition cd = cfm.getColumnDefinition(target.column);

            if (cd == null)
                throw new InvalidRequestException("No column definition found for column " + target.column);

            // TODO: we could lift that limitation
            if (cfm.isCompactTable() && cd.isPrimaryKeyColumn())
                throw new InvalidRequestException("Secondary indexes are not supported on PRIMARY KEY columns in COMPACT STORAGE tables");

            // It would be possible to support 2ndary index on static columns (but not without modifications of at least ExtendedFilter and
            // CompositesIndex) and maybe we should, but that means a query like:
            //     SELECT * FROM foo WHERE static_column = 'bar'
            // would pull the full partition every time the static column of partition is 'bar', which sounds like offering a
            // fair potential for foot-shooting, so I prefer leaving that to a follow up ticket once we have identified cases where
            // such indexing is actually useful.
            if (!cfm.isCompactTable() && cd.isStatic())
                throw new InvalidRequestException("Secondary indexes are not allowed on static columns");

            if (cd.kind == ColumnDefinition.Kind.PARTITION_KEY && cfm.getKeyValidatorAsClusteringComparator().size() == 1)
                throw new InvalidRequestException(String.format("Cannot create secondary index on partition key column %s", target.column));

            boolean isMap = cd.type instanceof MapType;
            boolean isFrozenCollection = cd.type.isCollection() && !cd.type.isMultiCell();
            if (isFrozenCollection)
            {
                validateForFrozenCollection(target);
            }
            else
            {
                validateNotFullIndex(target);
                validateIsSimpleIndexIfTargetColumnNotCollection(cd, target);
                validateTargetColumnIsMapIfIndexInvolvesKeys(isMap, target);
            }
        }

        if (!Strings.isNullOrEmpty(indexName))
        {
            if (Schema.instance.getKSMetaData(keyspace()).existingIndexNames(null).contains(indexName))
            {
                if (ifNotExists)
                    return;
                else
                    throw new InvalidRequestException(String.format("Index %s already exists", indexName));
            }
        }

        properties.validate();
    }

    private void validateForFrozenCollection(IndexTarget target) throws InvalidRequestException
    {
        if (target.type != IndexTarget.Type.FULL)
            throw new InvalidRequestException(String.format("Cannot create %s() index on frozen column %s. " +
                                                            "Frozen collections only support full() indexes",
                                                            target.type, target.column));
    }

    private void validateNotFullIndex(IndexTarget target) throws InvalidRequestException
    {
        if (target.type == IndexTarget.Type.FULL)
            throw new InvalidRequestException("full() indexes can only be created on frozen collections");
    }

    private void validateIsSimpleIndexIfTargetColumnNotCollection(ColumnDefinition cd, IndexTarget target) throws InvalidRequestException
    {
        if (!cd.type.isCollection() && target.type != IndexTarget.Type.SIMPLE)
            throw new InvalidRequestException(String.format("Cannot create %s() index on %s. " +
                                                            "Non-collection columns support only simple indexes",
                                                            target.type.toString(), target.column));
    }

    private void validateTargetColumnIsMapIfIndexInvolvesKeys(boolean isMap, IndexTarget target) throws InvalidRequestException
    {
        if (target.type == IndexTarget.Type.KEYS || target.type == IndexTarget.Type.KEYS_AND_VALUES)
        {
            if (!isMap)
                throw new InvalidRequestException(String.format("Cannot create index on %s of column %s with non-map type",
                                                                target.type, target.column));
        }
    }

    private void validateTargetsForMultiColumnIndex(List<IndexTarget> targets)
    {
        if (!properties.isCustom)
            throw new InvalidRequestException("Only CUSTOM indexes support multiple columns");

        Set<ColumnIdentifier> columns = new HashSet<>();
        for (IndexTarget target : targets)
            if (!columns.add(target.column))
                throw new InvalidRequestException("Duplicate column " + target.column + " in index target list");
    }

    public Event.SchemaChange announceMigration(boolean isLocalOnly) throws RequestValidationException
    {
        CFMetaData cfm = Schema.instance.getCFMetaData(keyspace(), columnFamily()).copy();
        List<IndexTarget> targets = new ArrayList<>(rawTargets.size());
        for (IndexTarget.Raw rawTarget : rawTargets)
            targets.add(rawTarget.prepare(cfm));

        String acceptedName = indexName;
        if (Strings.isNullOrEmpty(acceptedName))
        {
            acceptedName = Indexes.getAvailableIndexName(keyspace(),
                                                         columnFamily(),
                                                         targets.size() == 1 ? targets.get(0).column.toString() : null);
        }

        if (Schema.instance.getKSMetaData(keyspace()).existingIndexNames(null).contains(acceptedName))
        {
            if (ifNotExists)
                return null;
            else
                throw new InvalidRequestException(String.format("Index %s already exists", acceptedName));
        }

        IndexMetadata.Kind kind;
        Map<String, String> indexOptions;
        if (properties.isCustom)
        {
            kind = IndexMetadata.Kind.CUSTOM;
            indexOptions = properties.getOptions();
        }
        else
        {
            indexOptions = Collections.emptyMap();
            kind = cfm.isCompound() ? IndexMetadata.Kind.COMPOSITES : IndexMetadata.Kind.KEYS;
        }

        IndexMetadata index = IndexMetadata.fromIndexTargets(cfm, targets, acceptedName, kind, indexOptions);

        // check to disallow creation of an index which duplicates an existing one in all but name
        Optional<IndexMetadata> existingIndex = Iterables.tryFind(cfm.getIndexes(), existing -> existing.equalsWithoutName(index));
        if (existingIndex.isPresent())
        {
            if (ifNotExists)
                return null;
            else
                throw new InvalidRequestException(String.format("Index %s is a duplicate of existing index %s",
                                                                index.name,
                                                                existingIndex.get().name));
        }

        logger.trace("Updating index definition for {}", indexName);
        cfm.indexes(cfm.getIndexes().with(index));

        MigrationManager.announceColumnFamilyUpdate(cfm, isLocalOnly);

        // Creating an index is akin to updating the CF
        return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
    }
}
