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

import java.io.File;
import java.nio.ByteBuffer;
import java.util.*;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;

import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.partitions.PartitionUpdate;
import org.apache.cassandra.exceptions.CassandraException;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.schema.TriggerMetadata;
import org.apache.cassandra.schema.Triggers;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Pair;

public class TriggerExecutor
{
    public static final TriggerExecutor instance = new TriggerExecutor();

    private final Map<String, ITrigger> cachedTriggers = Maps.newConcurrentMap();
    private final ClassLoader parent = Thread.currentThread().getContextClassLoader();
    private volatile ClassLoader customClassLoader;

    private TriggerExecutor()
    {
        reloadClasses();
    }

    /**
     * Reload the triggers which is already loaded, Invoking this will update
     * the class loader so new jars can be loaded.
     */
    public void reloadClasses()
    {
        File triggerDirectory = FBUtilities.cassandraTriggerDir();
        if (triggerDirectory == null)
            return;
        customClassLoader = new CustomClassLoader(parent, triggerDirectory);
        cachedTriggers.clear();
    }

    /**
     * Augment a partition update by executing triggers to generate an intermediate
     * set of mutations, then merging the update from each mutation with those
     * supplied. This is called from @{link org.apache.cassandra.service.StorageProxy#cas}
     * which is scoped for a single partition. For that reason, any mutations generated
     * by triggers are checked to ensure that they are for the same table and partition
     * key as the primary update; if not, InvalidRequestException is thrown. If no
     * additional mutations are generated, the original updates are returned unmodified.
     *
     * @param updates partition update to be applied, contains the merge of the original
     *                update and any generated mutations
     * @return the final update to be applied, the original update merged with any
     * additional  mutations generated by configured triggers
     * @throws InvalidRequestException if any mutation generated by a trigger does not
     * apply to the exact same partition as the initial update
     */
    public PartitionUpdate execute(PartitionUpdate updates) throws InvalidRequestException
    {
        List<Mutation> intermediate = executeInternal(updates);
        if (intermediate == null || intermediate.isEmpty())
            return updates;

        return PartitionUpdate.merge(validateForSinglePartition(updates.metadata().cfId, updates.partitionKey(), intermediate));
    }

    /**
     * Takes a collection of mutations and possibly augments it by adding extra mutations
     * generated by configured triggers. If no additional mutations are created
     * this returns null, signalling to the caller that only the initial set of
     * mutations should be applied. If additional mutations <i>are</i> generated,
     * the total set (i.e. the original plus the additional mutations) are applied
     * together in a logged batch. Should this not be possible because the initial
     * mutations contain counter updates, InvalidRequestException is thrown.
     *
     * @param mutations initial collection of mutations
     * @return augmented mutations. Either the union of the initial and additional
     * mutations or null if no additional mutations were generated
     * @throws InvalidRequestException if additional mutations were generated, but
     * the initial mutations contains counter updates
     */
    public Collection<Mutation> execute(Collection<? extends IMutation> mutations) throws InvalidRequestException
    {
        boolean hasCounters = false;
        List<Mutation> augmentedMutations = null;

        for (IMutation mutation : mutations)
        {
            if (mutation instanceof CounterMutation)
                hasCounters = true;

            for (PartitionUpdate upd : mutation.getPartitionUpdates())
            {
                List<Mutation> augmentations = executeInternal(upd);
                if (augmentations == null || augmentations.isEmpty())
                    continue;

                validate(augmentations);

                if (augmentedMutations == null)
                    augmentedMutations = new LinkedList<>();
                augmentedMutations.addAll(augmentations);
            }
        }

        if (augmentedMutations == null)
            return null;

        if (hasCounters)
            throw new InvalidRequestException("Counter mutations and trigger mutations cannot be applied together atomically.");

        @SuppressWarnings("unchecked")
        Collection<Mutation> originalMutations = (Collection<Mutation>) mutations;

        return mergeMutations(Iterables.concat(originalMutations, augmentedMutations));
    }

    private Collection<Mutation> mergeMutations(Iterable<Mutation> mutations)
    {
        ListMultimap<Pair<String, ByteBuffer>, Mutation> groupedMutations = ArrayListMultimap.create();

        for (Mutation mutation : mutations)
        {
            Pair<String, ByteBuffer> key = Pair.create(mutation.getKeyspaceName(), mutation.key().getKey());
            groupedMutations.put(key, mutation);
        }

        List<Mutation> merged = new ArrayList<>(groupedMutations.size());
        for (Pair<String, ByteBuffer> key : groupedMutations.keySet())
            merged.add(Mutation.merge(groupedMutations.get(key)));

        return merged;
    }

    private List<PartitionUpdate> validateForSinglePartition(UUID cfId,
                                                                   DecoratedKey key,
                                                                   Collection<Mutation> tmutations)
    throws InvalidRequestException
    {
        validate(tmutations);

        if (tmutations.size() == 1)
        {
            List<PartitionUpdate> updates = Lists.newArrayList(Iterables.getOnlyElement(tmutations).getPartitionUpdates());
            if (updates.size() > 1)
                throw new InvalidRequestException("The updates generated by triggers are not all for the same partition");
            validateSamePartition(cfId, key, Iterables.getOnlyElement(updates));
            return updates;
        }

        ArrayList<PartitionUpdate> updates = new ArrayList<>(tmutations.size());
        for (Mutation mutation : tmutations)
        {
            for (PartitionUpdate update : mutation.getPartitionUpdates())
            {
                validateSamePartition(cfId, key, update);
                updates.add(update);
            }
        }
        return updates;
    }

    private void validateSamePartition(UUID cfId, DecoratedKey key, PartitionUpdate update)
    throws InvalidRequestException
    {
        if (!key.equals(update.partitionKey()))
            throw new InvalidRequestException("Partition key of additional mutation does not match primary update key");

        if (!cfId.equals(update.metadata().cfId))
            throw new InvalidRequestException("table of additional mutation does not match primary update table");
    }

    private void validate(Collection<Mutation> tmutations) throws InvalidRequestException
    {
        for (Mutation mutation : tmutations)
        {
            QueryProcessor.validateKey(mutation.key().getKey());
            for (PartitionUpdate update : mutation.getPartitionUpdates())
                update.validate();
        }
    }

    /**
     * Switch class loader before using the triggers for the column family, if
     * not loaded them with the custom class loader.
     */
    private List<Mutation> executeInternal(PartitionUpdate update)
    {
        Triggers triggers = update.metadata().getTriggers();
        if (triggers.isEmpty())
            return null;
        List<Mutation> tmutations = Lists.newLinkedList();
        Thread.currentThread().setContextClassLoader(customClassLoader);
        try
        {
            for (TriggerMetadata td : triggers)
            {
                ITrigger trigger = cachedTriggers.get(td.classOption);
                if (trigger == null)
                {
                    trigger = loadTriggerInstance(td.classOption);
                    cachedTriggers.put(td.classOption, trigger);
                }
                Collection<Mutation> temp = trigger.augment(update);
                if (temp != null)
                    tmutations.addAll(temp);
            }
            return tmutations;
        }
        catch (CassandraException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            throw new RuntimeException(String.format("Exception while executing trigger on table with ID: %s", update.metadata().cfId), ex);
        }
        finally
        {
            Thread.currentThread().setContextClassLoader(parent);
        }
    }

    public synchronized ITrigger loadTriggerInstance(String triggerName) throws Exception
    {
        // double check.
        if (cachedTriggers.get(triggerName) != null)
            return cachedTriggers.get(triggerName);
        return (ITrigger) customClassLoader.loadClass(triggerName).getConstructor().newInstance();
    }
}
