/*
 * 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.List;
import java.util.Locale;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.common.collect.MapMaker;

import org.apache.cassandra.cache.IMeasurableMemory;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.selection.Selectable;
import org.apache.cassandra.cql3.selection.Selector;
import org.apache.cassandra.cql3.selection.SimpleSelector;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.memory.AbstractAllocator;

/**
 * Represents an identifer for a CQL column definition.
 * TODO : should support light-weight mode without text representation for when not interned
 */
public class ColumnIdentifier extends Selectable implements IMeasurableMemory, Comparable<ColumnIdentifier>
{
    private static final Pattern PATTERN_DOUBLE_QUOTE = Pattern.compile("\"", Pattern.LITERAL);

    public final ByteBuffer bytes;
    private final String text;
    /**
     * since these objects are compared frequently, we stash an efficiently compared prefix of the bytes, in the expectation
     * that the majority of comparisons can be answered by this value only
     */
    public final long prefixComparison;
    private final boolean interned;

    private static final Pattern UNQUOTED_IDENTIFIER = Pattern.compile("[a-z][a-z0-9_]*");

    private static final long EMPTY_SIZE = ObjectSizes.measure(new ColumnIdentifier(ByteBufferUtil.EMPTY_BYTE_BUFFER, "", false));

    private static final ConcurrentMap<InternedKey, ColumnIdentifier> internedInstances = new MapMaker().weakValues().makeMap();

    private static final class InternedKey
    {
        private final AbstractType<?> type;
        private final ByteBuffer bytes;

        InternedKey(AbstractType<?> type, ByteBuffer bytes)
        {
            this.type = type;
            this.bytes = bytes;
        }

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

            if (o == null || getClass() != o.getClass())
                return false;

            InternedKey that = (InternedKey) o;
            return bytes.equals(that.bytes) && type.equals(that.type);
        }

        @Override
        public int hashCode()
        {
            return bytes.hashCode() + 31 * type.hashCode();
        }
    }

    private static long prefixComparison(ByteBuffer bytes)
    {
        long prefix = 0;
        ByteBuffer read = bytes.duplicate();
        int i = 0;
        while (read.hasRemaining() && i < 8)
        {
            prefix <<= 8;
            prefix |= read.get() & 0xFF;
            i++;
        }
        prefix <<= (8 - i) * 8;
        // by flipping the top bit (==Integer.MIN_VALUE), we ensure that signed comparison gives the same result
        // as an unsigned without the bit flipped
        prefix ^= Long.MIN_VALUE;
        return prefix;
    }

    public ColumnIdentifier(String rawText, boolean keepCase)
    {
        this.text = keepCase ? rawText : rawText.toLowerCase(Locale.US);
        this.bytes = ByteBufferUtil.bytes(this.text);
        this.prefixComparison = prefixComparison(bytes);
        this.interned = false;
    }

    public ColumnIdentifier(ByteBuffer bytes, AbstractType<?> type)
    {
        this(bytes, type.getString(bytes), false);
    }

    public ColumnIdentifier(ByteBuffer bytes, String text)
    {
        this(bytes, text, false);
    }

    private ColumnIdentifier(ByteBuffer bytes, String text, boolean interned)
    {
        this.bytes = bytes;
        this.text = text;
        this.interned = interned;
        this.prefixComparison = prefixComparison(bytes);
    }

    public static ColumnIdentifier getInterned(ByteBuffer bytes, AbstractType<?> type)
    {
        return getInterned(type, bytes, type.getString(bytes));
    }

    public static ColumnIdentifier getInterned(String rawText, boolean keepCase)
    {
        String text = keepCase ? rawText : rawText.toLowerCase(Locale.US);
        ByteBuffer bytes = ByteBufferUtil.bytes(text);
        return getInterned(UTF8Type.instance, bytes, text);
    }

    public static ColumnIdentifier getInterned(AbstractType<?> type, ByteBuffer bytes, String text)
    {
        bytes = ByteBufferUtil.minimalBufferFor(bytes);

        InternedKey key = new InternedKey(type, bytes);
        ColumnIdentifier id = internedInstances.get(key);
        if (id != null)
            return id;

        ColumnIdentifier created = new ColumnIdentifier(bytes, text, true);
        ColumnIdentifier previous = internedInstances.putIfAbsent(key, created);
        return previous == null ? created : previous;
    }

    public boolean isInterned()
    {
        return interned;
    }

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

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

        if(!(o instanceof ColumnIdentifier))
            return false;
        ColumnIdentifier that = (ColumnIdentifier)o;
        return bytes.equals(that.bytes);
    }

    @Override
    public String toString()
    {
        return text;
    }

    /**
     * Returns a string representation of the identifier that is safe to use directly in CQL queries.
     * In necessary, the string will be double-quoted, and any quotes inside the string will be escaped.
     */
    public String toCQLString()
    {
        return maybeQuote(text);
    }

    public long unsharedHeapSize()
    {
        return EMPTY_SIZE
             + ObjectSizes.sizeOnHeapOf(bytes)
             + ObjectSizes.sizeOf(text);
    }

    public long unsharedHeapSizeExcludingData()
    {
        return EMPTY_SIZE
             + ObjectSizes.sizeOnHeapExcludingData(bytes)
             + ObjectSizes.sizeOf(text);
    }

    public ColumnIdentifier clone(AbstractAllocator allocator)
    {
        return interned ? this : new ColumnIdentifier(allocator.clone(bytes), text, false);
    }

    public Selector.Factory newSelectorFactory(CFMetaData cfm, List<ColumnDefinition> defs) throws InvalidRequestException
    {
        ColumnDefinition def = cfm.getColumnDefinitionForCQL(this);
        if (def == null)
            throw new InvalidRequestException(String.format("Undefined name %s in selection clause", this));

        return SimpleSelector.newFactory(def, addAndGetIndex(def, defs));
    }

    public int compareTo(ColumnIdentifier that)
    {
        int c = Long.compare(this.prefixComparison, that.prefixComparison);
        if (c != 0)
            return c;
        if (this == that)
            return 0;
        return ByteBufferUtil.compareUnsigned(this.bytes, that.bytes);
    }

    /**
     * Because Thrift-created tables may have a non-text comparator, we cannot determine the proper 'key' until
     * we know the comparator. ColumnIdentifier.Raw is a placeholder that can be converted to a real ColumnIdentifier
     * once the comparator is known with prepare(). This should only be used with identifiers that are actual
     * column names. See CASSANDRA-8178 for more background.
     */
    public static interface Raw extends Selectable.Raw
    {

        public ColumnIdentifier prepare(CFMetaData cfm);

        /**
         * Returns a string representation of the identifier that is safe to use directly in CQL queries.
         * In necessary, the string will be double-quoted, and any quotes inside the string will be escaped.
         */
        public String toCQLString();
    }

    public static class Literal implements Raw
    {
        private final String rawText;
        private final String text;

        public Literal(String rawText, boolean keepCase)
        {
            this.rawText = rawText;
            this.text =  keepCase ? rawText : rawText.toLowerCase(Locale.US);
        }

        public ColumnIdentifier prepare(CFMetaData cfm)
        {
            if (!cfm.isStaticCompactTable())
                return getInterned(text, true);

            AbstractType<?> thriftColumnNameType = cfm.thriftColumnNameType();
            if (thriftColumnNameType instanceof UTF8Type)
                return getInterned(text, true);

            // We have a Thrift-created table with a non-text comparator. Check if we have a match column, otherwise assume we should use
            // thriftColumnNameType
            ByteBuffer bufferName = ByteBufferUtil.bytes(text);
            for (ColumnDefinition def : cfm.allColumns())
            {
                if (def.name.bytes.equals(bufferName))
                    return def.name;
            }
            return getInterned(thriftColumnNameType, thriftColumnNameType.fromString(rawText), text);
        }

        public boolean processesSelection()
        {
            return false;
        }

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

        @Override
        public final boolean equals(Object o)
        {
            if(!(o instanceof Literal))
                return false;

            Literal that = (Literal) o;
            return text.equals(that.text);
        }

        @Override
        public String toString()
        {
            return text;
        }

        public String toCQLString()
        {
            return maybeQuote(text);
        }
    }

    public static class ColumnIdentifierValue implements Raw
    {
        private final ColumnIdentifier identifier;

        public ColumnIdentifierValue(ColumnIdentifier identifier)
        {
            this.identifier = identifier;
        }

        public ColumnIdentifier prepare(CFMetaData cfm)
        {
            return identifier;
        }

        public boolean processesSelection()
        {
            return false;
        }

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

        @Override
        public final boolean equals(Object o)
        {
            if(!(o instanceof ColumnIdentifierValue))
                return false;
            ColumnIdentifierValue that = (ColumnIdentifierValue) o;
            return identifier.equals(that.identifier);
        }

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

        public String toCQLString()
        {
            return maybeQuote(identifier.text);
        }
    }

    public static String maybeQuote(String text)
    {
        if (UNQUOTED_IDENTIFIER.matcher(text).matches() && !ReservedKeywords.isReserved(text))
            return text;

        return '"' + PATTERN_DOUBLE_QUOTE.matcher(text).replaceAll(Matcher.quoteReplacement("\"\"")) + '"';
    }
}
