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

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

import org.apache.cassandra.cql3.functions.Function;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.db.marshal.UserType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.utils.ByteBufferUtil;

/**
 * Static helper methods and classes for user types.
 */
public abstract class UserTypes
{
    private UserTypes() {}

    public static ColumnSpecification fieldSpecOf(ColumnSpecification column, int field)
    {
        UserType ut = (UserType)column.type;
        return new ColumnSpecification(column.ksName,
                                       column.cfName,
                                       new ColumnIdentifier(column.name + "." + UTF8Type.instance.compose(ut.fieldName(field)), true),
                                       ut.fieldType(field));
    }

    public static class Literal extends Term.Raw
    {
        public final Map<ColumnIdentifier, Term.Raw> entries;

        public Literal(Map<ColumnIdentifier, Term.Raw> entries)
        {
            this.entries = entries;
        }

        public Term prepare(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
        {
            validateAssignableTo(keyspace, receiver);

            UserType ut = (UserType)receiver.type;
            boolean allTerminal = true;
            List<Term> values = new ArrayList<>(entries.size());
            int foundValues = 0;
            for (int i = 0; i < ut.size(); i++)
            {
                ColumnIdentifier field = new ColumnIdentifier(ut.fieldName(i), UTF8Type.instance);
                Term.Raw raw = entries.get(field);
                if (raw == null)
                    raw = Constants.NULL_LITERAL;
                else
                    ++foundValues;
                Term value = raw.prepare(keyspace, fieldSpecOf(receiver, i));

                if (value instanceof Term.NonTerminal)
                    allTerminal = false;

                values.add(value);
            }
            if (foundValues != entries.size())
            {
                // We had some field that are not part of the type
                for (ColumnIdentifier id : entries.keySet())
                    if (!ut.fieldNames().contains(id.bytes))
                        throw new InvalidRequestException(String.format("Unknown field '%s' in value of user defined type %s", id, ut.getNameAsString()));
            }

            DelayedValue value = new DelayedValue(((UserType)receiver.type), values);
            return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
        }

        private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
        {
            if (!(receiver.type instanceof UserType))
                throw new InvalidRequestException(String.format("Invalid user type literal for %s of type %s", receiver, receiver.type.asCQL3Type()));

            UserType ut = (UserType)receiver.type;
            for (int i = 0; i < ut.size(); i++)
            {
                ColumnIdentifier field = new ColumnIdentifier(ut.fieldName(i), UTF8Type.instance);
                Term.Raw value = entries.get(field);
                if (value == null)
                    continue;

                ColumnSpecification fieldSpec = fieldSpecOf(receiver, i);
                if (!value.testAssignment(keyspace, fieldSpec).isAssignable())
                    throw new InvalidRequestException(String.format("Invalid user type literal for %s: field %s is not of type %s", receiver, field, fieldSpec.type.asCQL3Type()));
            }
        }

        public AssignmentTestable.TestResult testAssignment(String keyspace, ColumnSpecification receiver)
        {
            try
            {
                validateAssignableTo(keyspace, receiver);
                return AssignmentTestable.TestResult.WEAKLY_ASSIGNABLE;
            }
            catch (InvalidRequestException e)
            {
                return AssignmentTestable.TestResult.NOT_ASSIGNABLE;
            }
        }

        public String getText()
        {
            StringBuilder sb = new StringBuilder();
            sb.append("{");
            Iterator<Map.Entry<ColumnIdentifier, Term.Raw>> iter = entries.entrySet().iterator();
            while (iter.hasNext())
            {
                Map.Entry<ColumnIdentifier, Term.Raw> entry = iter.next();
                sb.append(entry.getKey()).append(": ").append(entry.getValue().getText());
                if (iter.hasNext())
                    sb.append(", ");
            }
            sb.append("}");
            return sb.toString();
        }
    }

    // Same purpose than Lists.DelayedValue, except we do handle bind marker in that case
    public static class DelayedValue extends Term.NonTerminal
    {
        private final UserType type;
        private final List<Term> values;

        public DelayedValue(UserType type, List<Term> values)
        {
            this.type = type;
            this.values = values;
        }

        public void addFunctionsTo(List<Function> functions)
        {
            Terms.addFunctions(values, functions);
        }

        public boolean containsBindMarker()
        {
            for (Term t : values)
                if (t.containsBindMarker())
                    return true;
            return false;
        }

        public void collectMarkerSpecification(VariableSpecifications boundNames)
        {
            for (int i = 0; i < type.size(); i++)
                values.get(i).collectMarkerSpecification(boundNames);
        }

        private ByteBuffer[] bindInternal(QueryOptions options) throws InvalidRequestException
        {
            ByteBuffer[] buffers = new ByteBuffer[values.size()];
            for (int i = 0; i < type.size(); i++)
            {
                buffers[i] = values.get(i).bindAndGet(options);
                // Since A UDT value is always written in its entirety Cassandra can't preserve a pre-existing value by 'not setting' the new value. Reject the query.
                if (buffers[i] == ByteBufferUtil.UNSET_BYTE_BUFFER)
                    throw new InvalidRequestException(String.format("Invalid unset value for field '%s' of user defined type %s", type.fieldNameAsString(i), type.getNameAsString()));
            }
            return buffers;
        }

        public Constants.Value bind(QueryOptions options) throws InvalidRequestException
        {
            return new Constants.Value(bindAndGet(options));
        }

        @Override
        public ByteBuffer bindAndGet(QueryOptions options) throws InvalidRequestException
        {
            return UserType.buildValue(bindInternal(options));
        }
    }
}
