/*
 * 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.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;

import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.functions.Function;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.serializers.MarshalException;
import org.codehaus.jackson.io.JsonStringEncoder;
import org.codehaus.jackson.map.ObjectMapper;

/** Term-related classes for INSERT JSON support. */
public class Json
{
    public static final ObjectMapper JSON_OBJECT_MAPPER = new ObjectMapper();

    public static final ColumnIdentifier JSON_COLUMN_ID = new ColumnIdentifier("[json]", true);

    /**
     * Quotes string contents using standard JSON quoting.
     */
    public static String quoteAsJsonString(String s)
    {
        return new String(JsonStringEncoder.getInstance().quoteAsString(s));
    }

    public static Object decodeJson(String json)
    {
        try
        {
            return JSON_OBJECT_MAPPER.readValue(json, Object.class);
        }
        catch (IOException exc)
        {
            throw new MarshalException("Error decoding JSON string: " + exc.getMessage());
        }
    }

    public interface Raw
    {
        public Prepared prepareAndCollectMarkers(CFMetaData metadata, Collection<ColumnDefinition> receivers, VariableSpecifications boundNames);
    }

    /**
     * Represents a literal JSON string in an INSERT JSON statement.
     * For example: INSERT INTO mytable (key, col) JSON '{"key": 0, "col": 0}';
     */
    public static class Literal implements Raw
    {
        private final String text;

        public Literal(String text)
        {
            this.text = text;
        }

        public Prepared prepareAndCollectMarkers(CFMetaData metadata, Collection<ColumnDefinition> receivers, VariableSpecifications boundNames)
        {
            return new PreparedLiteral(parseJson(text, receivers));
        }
    }

    /**
     * Represents a marker for a JSON string in an INSERT JSON statement.
     * For example: INSERT INTO mytable (key, col) JSON ?;
     */
    public static class Marker implements Raw
    {
        protected final int bindIndex;

        public Marker(int bindIndex)
        {
            this.bindIndex = bindIndex;
        }

        public Prepared prepareAndCollectMarkers(CFMetaData metadata, Collection<ColumnDefinition> receivers, VariableSpecifications boundNames)
        {
            boundNames.add(bindIndex, makeReceiver(metadata));
            return new PreparedMarker(bindIndex, receivers);
        }

        private ColumnSpecification makeReceiver(CFMetaData metadata)
        {
            return new ColumnSpecification(metadata.ksName, metadata.cfName, JSON_COLUMN_ID, UTF8Type.instance);
        }
    }

    /**
     * A prepared, full set of JSON values.
     */
    public static abstract class Prepared
    {
        public abstract Term.Raw getRawTermForColumn(ColumnDefinition def);
    }

    /**
     * A prepared literal set of JSON values
     */
    private static class PreparedLiteral extends Prepared
    {
        private final Map<ColumnIdentifier, Term> columnMap;

        public PreparedLiteral(Map<ColumnIdentifier, Term> columnMap)
        {
            this.columnMap = columnMap;
        }

        public Term.Raw getRawTermForColumn(ColumnDefinition def)
        {
            Term value = columnMap.get(def.name);
            return value == null ? Constants.NULL_LITERAL : new ColumnValue(value);
        }
    }

    /**
     *  A prepared bind marker for a set of JSON values
     */
    private static class PreparedMarker extends Prepared
    {
        private final int bindIndex;
        private final Collection<ColumnDefinition> columns;

        public PreparedMarker(int bindIndex, Collection<ColumnDefinition> columns)
        {
            this.bindIndex = bindIndex;
            this.columns = columns;
        }

        public RawDelayedColumnValue getRawTermForColumn(ColumnDefinition def)
        {
            return new RawDelayedColumnValue(this, def);
        }
    }

    /**
     * A Terminal for a single column.
     *
     * Note that this is intrinsically an already prepared term, but this still implements Term.Raw so that we can
     * easily use it to create raw operations.
     */
    private static class ColumnValue extends Term.Raw
    {
        private final Term term;

        public ColumnValue(Term term)
        {
            this.term = term;
        }

        @Override
        public Term prepare(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
        {
            return term;
        }

        @Override
        public TestResult testAssignment(String keyspace, ColumnSpecification receiver)
        {
            return TestResult.NOT_ASSIGNABLE;
        }

        public String getText()
        {
            return term.toString();
        }
    }

    /**
     * A Raw term for a single column. Like ColumnValue, this is intrinsically already prepared.
     */
    private static class RawDelayedColumnValue extends Term.Raw
    {
        private final PreparedMarker marker;
        private final ColumnDefinition column;

        public RawDelayedColumnValue(PreparedMarker prepared, ColumnDefinition column)
        {
            this.marker = prepared;
            this.column = column;
        }

        @Override
        public Term prepare(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
        {
            return new DelayedColumnValue(marker, column);
        }

        @Override
        public TestResult testAssignment(String keyspace, ColumnSpecification receiver)
        {
            return TestResult.WEAKLY_ASSIGNABLE;
        }

        public String getText()
        {
            return marker.toString();
        }
    }

    /**
     * A NonTerminal for a single column. As with {@code ColumnValue}, this is intrinsically a prepared.
     */
    private static class DelayedColumnValue extends Term.NonTerminal
    {
        private final PreparedMarker marker;
        private final ColumnDefinition column;

        public DelayedColumnValue(PreparedMarker prepared, ColumnDefinition column)
        {
            this.marker = prepared;
            this.column = column;
        }

        @Override
        public void collectMarkerSpecification(VariableSpecifications boundNames)
        {
            // We've already collected what we should (and in practice this method is never called).
        }

        @Override
        public boolean containsBindMarker()
        {
            return true;
        }

        @Override
        public Terminal bind(QueryOptions options) throws InvalidRequestException
        {
            Term term = options.getJsonColumnValue(marker.bindIndex, column.name, marker.columns);
            return term == null ? null : term.bind(options);
        }

        @Override
        public void addFunctionsTo(List<Function> functions)
        {
        }
    }

    /**
     * Given a JSON string, return a map of columns to their values for the insert.
     */
    public static Map<ColumnIdentifier, Term> parseJson(String jsonString, Collection<ColumnDefinition> expectedReceivers)
    {
        try
        {
            Map<String, Object> valueMap = JSON_OBJECT_MAPPER.readValue(jsonString, Map.class);

            if (valueMap == null)
                throw new InvalidRequestException("Got null for INSERT JSON values");

            handleCaseSensitivity(valueMap);

            Map<ColumnIdentifier, Term> columnMap = new HashMap<>(expectedReceivers.size());
            for (ColumnSpecification spec : expectedReceivers)
            {
                Object parsedJsonObject = valueMap.remove(spec.name.toString());
                if (parsedJsonObject == null)
                {
                    columnMap.put(spec.name, null);
                }
                else
                {
                    try
                    {
                        columnMap.put(spec.name, spec.type.fromJSONObject(parsedJsonObject));
                    }
                    catch(MarshalException exc)
                    {
                        throw new InvalidRequestException(String.format("Error decoding JSON value for %s: %s", spec.name, exc.getMessage()));
                    }
                }
            }

            if (!valueMap.isEmpty())
            {
                throw new InvalidRequestException(String.format(
                        "JSON values map contains unrecognized column: %s", valueMap.keySet().iterator().next()));
            }

            return columnMap;
        }
        catch (IOException exc)
        {
            throw new InvalidRequestException(String.format("Could not decode JSON string as a map: %s. (String was: %s)", exc.toString(), jsonString));
        }
        catch (MarshalException exc)
        {
            throw new InvalidRequestException(exc.getMessage());
        }
    }

    /**
     * Handles unquoting and case-insensitivity in map keys.
     */
    public static void handleCaseSensitivity(Map<String, Object> valueMap)
    {
        for (String mapKey : new ArrayList<>(valueMap.keySet()))
        {
            // if it's surrounded by quotes, remove them and preserve the case
            if (mapKey.startsWith("\"") && mapKey.endsWith("\""))
            {
                valueMap.put(mapKey.substring(1, mapKey.length() - 1), valueMap.remove(mapKey));
                continue;
            }

            // otherwise, lowercase it if needed
            String lowered = mapKey.toLowerCase(Locale.US);
            if (!mapKey.equals(lowered))
                valueMap.put(lowered, valueMap.remove(mapKey));
        }
    }
}
