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

import java.nio.ByteBuffer;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import javax.annotation.Nullable;

import com.google.common.collect.*;

import org.apache.cassandra.cql3.FieldIdentifier;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.UserType;
import org.apache.cassandra.exceptions.ConfigurationException;

import static java.lang.String.format;
import static java.util.stream.Collectors.toList;

import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.transform;

import static org.apache.cassandra.utils.ByteBufferUtil.bytes;

/**
 * An immutable container for a keyspace's UDTs.
 */
public final class Types implements Iterable<UserType>
{
    private static final Types NONE = new Types(ImmutableMap.of());

    private final Map<ByteBuffer, UserType> types;

    private Types(Builder builder)
    {
        types = builder.types.build();
    }

    /*
     * For use in RawBuilder::build only.
     */
    private Types(Map<ByteBuffer, UserType> types)
    {
        this.types = types;
    }

    public static Builder builder()
    {
        return new Builder();
    }

    public static RawBuilder rawBuilder(String keyspace)
    {
        return new RawBuilder(keyspace);
    }

    public static Types none()
    {
        return NONE;
    }

    public static Types of(UserType... types)
    {
        return builder().add(types).build();
    }

    public Iterator<UserType> iterator()
    {
        return types.values().iterator();
    }

    public Stream<UserType> stream()
    {
        return StreamSupport.stream(spliterator(), false);
    }

    /**
     * Returns a stream of user types sorted by dependencies
     * @return a stream of user types sorted by dependencies
     */
    public Stream<UserType> sortedStream()
    {
        Set<ByteBuffer> sorted = new LinkedHashSet<>();
        types.values().forEach(t -> addUserTypes(t, sorted));
        return sorted.stream().map(n -> types.get(n));
    }

    public Iterable<UserType> referencingUserType(ByteBuffer name)
    {
        return Iterables.filter(types.values(), t -> t.referencesUserType(name) && !t.name.equals(name));
    }

    public boolean isEmpty()
    {
        return types.isEmpty();
    }

    /**
     * Get the type with the specified name
     *
     * @param name a non-qualified type name
     * @return an empty {@link Optional} if the type name is not found; a non-empty optional of {@link UserType} otherwise
     */
    public Optional<UserType> get(ByteBuffer name)
    {
        return Optional.ofNullable(types.get(name));
    }

    /**
     * Get the type with the specified name
     *
     * @param name a non-qualified type name
     * @return null if the type name is not found; the found {@link UserType} otherwise
     */
    @Nullable
    public UserType getNullable(ByteBuffer name)
    {
        return types.get(name);
    }

    boolean containsType(ByteBuffer name)
    {
        return types.containsKey(name);
    }

    Types filter(Predicate<UserType> predicate)
    {
        Builder builder = builder();
        types.values().stream().filter(predicate).forEach(builder::add);
        return builder.build();
    }

    /**
     * Create a Types instance with the provided type added
     */
    public Types with(UserType type)
    {
        if (get(type.name).isPresent())
            throw new IllegalStateException(format("Type %s already exists", type.name));

        return builder().add(this).add(type).build();
    }

    /**
     * Creates a Types instance with the type with the provided name removed
     */
    public Types without(ByteBuffer name)
    {
        UserType type =
            get(name).orElseThrow(() -> new IllegalStateException(format("Type %s doesn't exists", name)));

        return without(type);
    }

    public Types without(UserType type)
    {
        return filter(t -> t != type);
    }

    public Types withUpdatedUserType(UserType udt)
    {
        return any(this, t -> t.referencesUserType(udt.name))
             ? builder().add(transform(this, t -> t.withUpdatedUserType(udt))).build()
             : this;
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o)
            return true;

        if (!(o instanceof Types))
            return false;

        Types other = (Types) o;

        if (types.size() != other.types.size())
            return false;

        Iterator<Map.Entry<ByteBuffer, UserType>> thisIter = this.types.entrySet().iterator();
        Iterator<Map.Entry<ByteBuffer, UserType>> otherIter = other.types.entrySet().iterator();
        while (thisIter.hasNext())
        {
            Map.Entry<ByteBuffer, UserType> thisNext = thisIter.next();
            Map.Entry<ByteBuffer, UserType> otherNext = otherIter.next();
            if (!thisNext.getKey().equals(otherNext.getKey()))
                return false;

            if (!thisNext.getValue().equals(otherNext.getValue()))
                return false;
        }
        return true;
    }

    @Override
    public int hashCode()
    {
        return types.hashCode();
    }

    @Override
    public String toString()
    {
        return types.values().toString();
    }

    /**
     * Sorts the types by dependencies.
     *
     * @param types the types to sort
     * @return the types sorted by dependencies and names
     */
    private static Set<ByteBuffer> sortByDependencies(Collection<UserType> types)
    {
        Set<ByteBuffer> sorted = new LinkedHashSet<>();
        types.stream().forEach(t -> addUserTypes(t, sorted));
        return sorted;
    }

    /**
     * Find all user types used by the specified type and add them to the set.
     *
     * @param type the type to check for user types.
     * @param types the set of UDT names to which to add new user types found in {@code type}. Note that the
     * insertion ordering is important and ensures that if a user type A uses another user type B, then B will appear
     * before A in iteration order.
     */
    private static void addUserTypes(AbstractType<?> type, Set<ByteBuffer> types)
    {
        // Reach into subtypes first, so that if the type is a UDT, it's dependencies are recreated first.
        type.subTypes().forEach(t -> addUserTypes(t, types));

        if (type.isUDT())
            types.add(((UserType) type).name);
    }

    public static final class Builder
    {
        final ImmutableSortedMap.Builder<ByteBuffer, UserType> types = ImmutableSortedMap.naturalOrder();

        private Builder()
        {
        }

        public Types build()
        {
            return new Types(this);
        }

        public Builder add(UserType type)
        {
            assert type.isMultiCell();
            types.put(type.name, type);
            return this;
        }

        public Builder add(UserType... types)
        {
            for (UserType type : types)
                add(type);
            return this;
        }

        public Builder add(Iterable<UserType> types)
        {
            types.forEach(this::add);
            return this;
        }
    }

    public static final class RawBuilder
    {
        final String keyspace;
        final List<RawUDT> definitions;

        private RawBuilder(String keyspace)
        {
            this.keyspace = keyspace;
            this.definitions = new ArrayList<>();
        }

        /**
         * Build a Types instance from Raw definitions.
         *
         * Constructs a DAG of graph dependencies and resolves them 1 by 1 in topological order.
         */
        public Types build()
        {
            if (definitions.isEmpty())
                return Types.none();

            /*
             * build a DAG of UDT dependencies
             */
            Map<RawUDT, Integer> vertices = Maps.newHashMapWithExpectedSize(definitions.size()); // map values are numbers of referenced types
            for (RawUDT udt : definitions)
                vertices.put(udt, 0);

            Multimap<RawUDT, RawUDT> adjacencyList = HashMultimap.create();
            for (RawUDT udt1 : definitions)
                for (RawUDT udt2 : definitions)
                    if (udt1 != udt2 && udt1.referencesUserType(udt2))
                        adjacencyList.put(udt2, udt1);

            /*
             * resolve dependencies in topological order, using Kahn's algorithm
             */
            adjacencyList.values().forEach(vertex -> vertices.put(vertex, vertices.get(vertex) + 1));

            Queue<RawUDT> resolvableTypes = new LinkedList<>(); // UDTs with 0 dependencies
            for (Map.Entry<RawUDT, Integer> entry : vertices.entrySet())
                if (entry.getValue() == 0)
                    resolvableTypes.add(entry.getKey());

            Types types = new Types(new HashMap<>());
            while (!resolvableTypes.isEmpty())
            {
                RawUDT vertex = resolvableTypes.remove();

                for (RawUDT dependentType : adjacencyList.get(vertex))
                    if (vertices.replace(dependentType, vertices.get(dependentType) - 1) == 1)
                        resolvableTypes.add(dependentType);

                UserType udt = vertex.prepare(keyspace, types);
                types.types.put(udt.name, udt);
            }

            if (types.types.size() != definitions.size())
                throw new ConfigurationException(format("Cannot resolve UDTs for keyspace %s: some types are missing", keyspace));

            /*
             * return an immutable copy
             */
            return Types.builder().add(types).build();
        }

        public void add(String name, List<String> fieldNames, List<String> fieldTypes)
        {
            List<CQL3Type.Raw> rawFieldTypes =
                fieldTypes.stream()
                          .map(CQLTypeParser::parseRaw)
                          .collect(toList());

            definitions.add(new RawUDT(name, fieldNames, rawFieldTypes));
        }

        private static final class RawUDT
        {
            final String name;
            final List<String> fieldNames;
            final List<CQL3Type.Raw> fieldTypes;

            RawUDT(String name, List<String> fieldNames, List<CQL3Type.Raw> fieldTypes)
            {
                this.name = name;
                this.fieldNames = fieldNames;
                this.fieldTypes = fieldTypes;
            }

            boolean referencesUserType(RawUDT other)
            {
                return fieldTypes.stream().anyMatch(t -> t.referencesUserType(other.name));
            }

            UserType prepare(String keyspace, Types types)
            {
                List<FieldIdentifier> preparedFieldNames =
                    fieldNames.stream()
                              .map(FieldIdentifier::forInternalString)
                              .collect(toList());

                List<AbstractType<?>> preparedFieldTypes =
                    fieldTypes.stream()
                              .map(t -> t.prepareInternal(keyspace, types).getType())
                              .collect(toList());

                return new UserType(keyspace, bytes(name), preparedFieldNames, preparedFieldTypes, true);
            }

            @Override
            public int hashCode()
            {
                return name.hashCode();
            }

            @Override
            public boolean equals(Object other)
            {
                return name.equals(((RawUDT) other).name);
            }
        }
    }

    static TypesDiff diff(Types before, Types after)
    {
        return TypesDiff.diff(before, after);
    }

    static final class TypesDiff extends Diff<Types, UserType>
    {
        private static final TypesDiff NONE = new TypesDiff(Types.none(), Types.none(), ImmutableList.of());

        private TypesDiff(Types created, Types dropped, ImmutableCollection<Altered<UserType>> altered)
        {
            super(created, dropped, altered);
        }

        private static TypesDiff diff(Types before, Types after)
        {
            if (before == after)
                return NONE;

            Types created = after.filter(t -> !before.containsType(t.name));
            Types dropped = before.filter(t -> !after.containsType(t.name));

            ImmutableList.Builder<Altered<UserType>> altered = ImmutableList.builder();
            before.forEach(typeBefore ->
            {
                UserType typeAfter = after.getNullable(typeBefore.name);
                if (null != typeAfter)
                    typeBefore.compare(typeAfter).ifPresent(kind -> altered.add(new Altered<>(typeBefore, typeAfter, kind)));
            });

            return new TypesDiff(created, dropped, altered.build());
        }
    }
}
