/*
 * 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.config.ColumnDefinition;
import org.apache.cassandra.cql3.functions.Function;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.db.rows.CellPath;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.utils.ByteBufferUtil;

import static org.apache.cassandra.cql3.Constants.UNSET_VALUE;

/**
 * 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 + "." + ut.fieldName(field), true),
                                       ut.fieldType(field));
    }

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

        public Literal(Map<FieldIdentifier, 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++)
            {
                FieldIdentifier field = ut.fieldName(i);
                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 (FieldIdentifier id : entries.keySet())
                {
                    if (!ut.fieldNames().contains(id))
                        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.isUDT())
                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++)
            {
                FieldIdentifier field = ut.fieldName(i);
                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 AbstractType<?> getExactTypeIfKnown(String keyspace)
        {
            return null;
        }

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

    public static class Value extends Term.MultiItemTerminal
    {
        private final UserType type;
        public final ByteBuffer[] elements;

        public Value(UserType type, ByteBuffer[] elements)
        {
            this.type = type;
            this.elements = elements;
        }

        public static Value fromSerialized(ByteBuffer bytes, UserType type)
        {
            ByteBuffer[] values = type.split(bytes);
            if (values.length > type.size())
            {
                throw new InvalidRequestException(String.format(
                        "UDT value contained too many fields (expected %s, got %s)", type.size(), values.length));
            }

            return new Value(type, type.split(bytes));
        }

        public ByteBuffer get(int protocolVersion)
        {
            return TupleType.buildValue(elements);
        }

        public boolean equals(UserType userType, Value v)
        {
            if (elements.length != v.elements.length)
                return false;

            for (int i = 0; i < elements.length; i++)
                if (userType.fieldType(i).compare(elements[i], v.elements[i]) != 0)
                    return false;

            return true;
        }

        public List<ByteBuffer> getElements()
        {
            return Arrays.asList(elements);
        }
    }

    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
        {
            if (values.size() > type.size())
            {
                throw new InvalidRequestException(String.format(
                        "UDT value contained too many fields (expected %s, got %s)", type.size(), values.size()));
            }

            ByteBuffer[] buffers = new ByteBuffer[values.size()];
            for (int i = 0; i < type.size(); i++)
            {
                buffers[i] = values.get(i).bindAndGet(options);
                // Since a frozen 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 (!type.isMultiCell() && 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 Value bind(QueryOptions options) throws InvalidRequestException
        {
            return new Value(type, bindInternal(options));
        }

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

    public static class Marker extends AbstractMarker
    {
        protected Marker(int bindIndex, ColumnSpecification receiver)
        {
            super(bindIndex, receiver);
            assert receiver.type.isUDT();
        }

        public Terminal bind(QueryOptions options) throws InvalidRequestException
        {
            ByteBuffer value = options.getValues().get(bindIndex);
            if (value == null)
                return null;
            if (value == ByteBufferUtil.UNSET_BYTE_BUFFER)
                return UNSET_VALUE;
            return Value.fromSerialized(value, (UserType) receiver.type);
        }
    }

    public static class Setter extends Operation
    {
        public Setter(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
        {
            Term.Terminal value = t.bind(params.options);
            if (value == UNSET_VALUE)
                return;

            Value userTypeValue = (Value) value;
            if (column.type.isMultiCell())
            {
                // setting a whole UDT at once means we overwrite all cells, so delete existing cells
                params.setComplexDeletionTimeForOverwrite(column);
                if (value == null)
                    return;

                Iterator<FieldIdentifier> fieldNameIter = userTypeValue.type.fieldNames().iterator();
                for (ByteBuffer buffer : userTypeValue.elements)
                {
                    assert fieldNameIter.hasNext();
                    FieldIdentifier fieldName = fieldNameIter.next();
                    if (buffer == null)
                        continue;

                    CellPath fieldPath = userTypeValue.type.cellPathForField(fieldName);
                    params.addCell(column, fieldPath, buffer);
                }
            }
            else
            {
                // for frozen UDTs, we're overwriting the whole cell value
                if (value == null)
                    params.addTombstone(column);
                else
                    params.addCell(column, value.get(params.options.getProtocolVersion()));
            }
        }
    }

    public static class SetterByField extends Operation
    {
        private final FieldIdentifier field;

        public SetterByField(ColumnDefinition column, FieldIdentifier field, Term t)
        {
            super(column, t);
            this.field = field;
        }

        public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
        {
            // we should not get here for frozen UDTs
            assert column.type.isMultiCell() : "Attempted to set an individual field on a frozen UDT";

            Term.Terminal value = t.bind(params.options);
            if (value == UNSET_VALUE)
                return;

            CellPath fieldPath = ((UserType) column.type).cellPathForField(field);
            if (value == null)
                params.addTombstone(column, fieldPath);
            else
                params.addCell(column, fieldPath, value.get(params.options.getProtocolVersion()));
        }
    }

    public static class DeleterByField extends Operation
    {
        private final FieldIdentifier field;

        public DeleterByField(ColumnDefinition column, FieldIdentifier field)
        {
            super(column, null);
            this.field = field;
        }

        public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
        {
            // we should not get here for frozen UDTs
            assert column.type.isMultiCell() : "Attempted to delete a single field from a frozen UDT";

            CellPath fieldPath = ((UserType) column.type).cellPathForField(field);
            params.addTombstone(column, fieldPath);
        }
    }
}
