/*
 * 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<ByteBuffer, ColumnIdentifier> internedInstances = new MapMaker().weakValues().makeMap();

    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);
    }

    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(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(bytes, text);
    }

    public static ColumnIdentifier getInterned(ByteBuffer bytes, String text)
    {
        ColumnIdentifier id = internedInstances.get(bytes);
        if (id != null)
            return id;

        ColumnIdentifier created = new ColumnIdentifier(bytes, text, true);
        ColumnIdentifier previous = internedInstances.putIfAbsent(bytes, 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.getColumnDefinition(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.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);
        }
    }

    static String maybeQuote(String text)
    {
        if (UNQUOTED_IDENTIFIER.matcher(text).matches())
            return text;
        return '"' + PATTERN_DOUBLE_QUOTE.matcher(text).replaceAll(Matcher.quoteReplacement("\"\"")) + '"';
    }
}
