/*
 * 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.db.filter;

import java.io.IOException;
import java.util.*;

import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;

import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.rows.Cell;
import org.apache.cassandra.db.rows.CellPath;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;

/**
 * Represents which (non-PK) columns (and optionally which sub-part of a column for complex columns) are selected
 * by a query.
 *
 * In practice, this class cover 2 main cases:
 *   1) most user queries have to internally query all columns, because the CQL semantic requires us to know if
 *      a row is live or not even if it has no values for the columns requested by the user (see #6588for more
 *      details). However, while we need to know for columns if it has live values, we can actually save from
 *      sending the values for those columns that will not be returned to the user.
 *   2) for some internal queries (and for queries using #6588 if we introduce it), we're actually fine only
 *      actually querying some of the columns.
 *
 * For complex columns, this class allows to be more fine grained than the column by only selection some of the
 * cells of the complex column (either individual cell by path name, or some slice).
 */
public class ColumnFilter
{
    public static final Serializer serializer = new Serializer();

    // Distinguish between the 2 cases described above: if 'isFetchAll' is true, then all columns will be retrieved
    // by the query, but the values for column/cells not selected by 'selection' and 'subSelections' will be skipped.
    // Otherwise, only the column/cells returned by 'selection' and 'subSelections' will be returned at all.
    private final boolean isFetchAll;

    private final CFMetaData metadata; // can be null if !isFetchAll

    private final PartitionColumns selection; // can be null if isFetchAll and we don't want to skip any value
    private final SortedSetMultimap<ColumnIdentifier, ColumnSubselection> subSelections; // can be null

    private ColumnFilter(boolean isFetchAll,
                         CFMetaData metadata,
                         PartitionColumns columns,
                         SortedSetMultimap<ColumnIdentifier, ColumnSubselection> subSelections)
    {
        this.isFetchAll = isFetchAll;
        this.metadata = metadata;
        this.selection = columns;
        this.subSelections = subSelections;
    }

    /**
     * A selection that includes all columns (and their values).
     */
    public static ColumnFilter all(CFMetaData metadata)
    {
        return new ColumnFilter(true, metadata, null, null);
    }

    /**
     * A selection that only fetch the provided columns.
     * <p>
     * Note that this shouldn't be used for CQL queries in general as all columns should be queried to
     * preserve CQL semantic (see class javadoc). This is ok for some internal queries however (and
     * for #6588 if/when we implement it).
     */
    public static ColumnFilter selection(PartitionColumns columns)
    {
        return new ColumnFilter(false, null, columns, null);
    }

    /**
     * The columns that needs to be fetched internally for this selection.
     * <p>
     * This is the columns that must be present in the internal rows returned by queries using this selection,
     * not the columns that are actually queried by the user (see the class javadoc for details).
     *
     * @return the column to fetch for this selection.
     */
    public PartitionColumns fetchedColumns()
    {
        return isFetchAll ? metadata.partitionColumns() : selection;
    }

    public boolean includesAllColumns()
    {
        return isFetchAll;
    }

    /**
     * Whether the provided column is selected by this selection.
     */
    public boolean includes(ColumnDefinition column)
    {
        return isFetchAll || selection.contains(column);
    }

    /**
     * Whether we can skip the value for the provided selected column.
     */
    public boolean canSkipValue(ColumnDefinition column)
    {
        // We don't use that currently, see #10655 for more details.
        return false;
    }

    /**
     * Whether the provided cell of a complex column is selected by this selection.
     */
    public boolean includes(Cell cell)
    {
        if (isFetchAll || subSelections == null || !cell.column().isComplex())
            return true;

        SortedSet<ColumnSubselection> s = subSelections.get(cell.column().name);
        if (s.isEmpty())
            return true;

        for (ColumnSubselection subSel : s)
            if (subSel.compareInclusionOf(cell.path()) == 0)
                return true;

        return false;
    }

    /**
     * Whether we can skip the value of the cell of a complex column.
     */
    public boolean canSkipValue(ColumnDefinition column, CellPath path)
    {
        if (!isFetchAll || subSelections == null || !column.isComplex())
            return false;

        SortedSet<ColumnSubselection> s = subSelections.get(column.name);
        if (s.isEmpty())
            return false;

        for (ColumnSubselection subSel : s)
            if (subSel.compareInclusionOf(path) == 0)
                return false;

        return true;
    }

    /**
     * Creates a new {@code Tester} to efficiently test the inclusion of cells of complex column
     * {@code column}.
     */
    public Tester newTester(ColumnDefinition column)
    {
        if (subSelections == null || !column.isComplex())
            return null;

        SortedSet<ColumnSubselection> s = subSelections.get(column.name);
        if (s.isEmpty())
            return null;

        return new Tester(isFetchAll, s.iterator());
    }

    /**
     * Returns a {@code ColumnFilter}} builder that includes all columns (so the selections
     * added to the builder are the columns/cells for which we shouldn't skip the values).
     */
    public static Builder allColumnsBuilder(CFMetaData metadata)
    {
        return new Builder(metadata);
    }

    /**
     * Returns a {@code ColumnFilter}} builder that includes only the columns/cells
     * added to the builder.
     */
    public static Builder selectionBuilder()
    {
        return new Builder(null);
    }

    public static class Tester
    {
        private final boolean isFetchAll;
        private ColumnSubselection current;
        private final Iterator<ColumnSubselection> iterator;

        private Tester(boolean isFetchAll, Iterator<ColumnSubselection> iterator)
        {
            this.isFetchAll = isFetchAll;
            this.iterator = iterator;
        }

        public boolean includes(CellPath path)
        {
            return isFetchAll || includedBySubselection(path);
        }

        public boolean canSkipValue(CellPath path)
        {
            return isFetchAll && !includedBySubselection(path);
        }

        private boolean includedBySubselection(CellPath path)
        {
            while (current != null || iterator.hasNext())
            {
                if (current == null)
                    current = iterator.next();

                int cmp = current.compareInclusionOf(path);
                if (cmp == 0) // The path is included
                    return true;
                else if (cmp < 0) // The path is before this sub-selection, it's not included by any
                    return false;

                // the path is after this sub-selection, we need to check the next one.
                current = null;
            }
            return false;
        }
    }

    public static class Builder
    {
        private final CFMetaData metadata;
        private PartitionColumns.Builder selection;
        private List<ColumnSubselection> subSelections;

        private Builder(CFMetaData metadata)
        {
            this.metadata = metadata;
        }

        public Builder add(ColumnDefinition c)
        {
            if (selection == null)
                selection = PartitionColumns.builder();
            selection.add(c);
            return this;
        }

        public Builder addAll(Iterable<ColumnDefinition> columns)
        {
            if (selection == null)
                selection = PartitionColumns.builder();
            selection.addAll(columns);
            return this;
        }

        private Builder addSubSelection(ColumnSubselection subSelection)
        {
            add(subSelection.column());
            if (subSelections == null)
                subSelections = new ArrayList<>();
            subSelections.add(subSelection);
            return this;
        }

        public Builder slice(ColumnDefinition c, CellPath from, CellPath to)
        {
            return addSubSelection(ColumnSubselection.slice(c, from, to));
        }

        public Builder select(ColumnDefinition c, CellPath elt)
        {
            return addSubSelection(ColumnSubselection.element(c, elt));
        }

        public ColumnFilter build()
        {
            boolean isFetchAll = metadata != null;

            PartitionColumns selectedColumns = selection == null ? null : selection.build();
            // It's only ok to have selection == null in ColumnFilter if isFetchAll. So deal with the case of a "selection" builder
            // with nothing selected (we can at least happen on some backward compatible queries - CASSANDRA-10471).
            if (!isFetchAll && selectedColumns == null)
                selectedColumns = PartitionColumns.NONE;

            SortedSetMultimap<ColumnIdentifier, ColumnSubselection> s = null;
            if (subSelections != null)
            {
                s = TreeMultimap.create(Comparator.<ColumnIdentifier>naturalOrder(), Comparator.<ColumnSubselection>naturalOrder());
                for (ColumnSubselection subSelection : subSelections)
                    s.put(subSelection.column().name, subSelection);
            }

            return new ColumnFilter(isFetchAll, metadata, selectedColumns, s);
        }
    }

    @Override
    public String toString()
    {
        if (isFetchAll)
            return "*";

        if (selection.isEmpty())
            return "";

        Iterator<ColumnDefinition> defs = selection.selectOrderIterator();
        if (!defs.hasNext())
            return "<none>";

        StringBuilder sb = new StringBuilder();
        appendColumnDef(sb, defs.next());
        while (defs.hasNext())
            appendColumnDef(sb.append(", "), defs.next());
        return sb.toString();
    }

    private void appendColumnDef(StringBuilder sb, ColumnDefinition column)
    {
        if (subSelections == null)
        {
            sb.append(column.name);
            return;
        }

        SortedSet<ColumnSubselection> s = subSelections.get(column.name);
        if (s.isEmpty())
        {
            sb.append(column.name);
            return;
        }

        int i = 0;
        for (ColumnSubselection subSel : s)
            sb.append(i++ == 0 ? "" : ", ").append(column.name).append(subSel);
    }

    public static class Serializer
    {
        private static final int IS_FETCH_ALL_MASK       = 0x01;
        private static final int HAS_SELECTION_MASK      = 0x02;
        private static final int HAS_SUB_SELECTIONS_MASK = 0x04;

        private static int makeHeaderByte(ColumnFilter selection)
        {
            return (selection.isFetchAll ? IS_FETCH_ALL_MASK : 0)
                 | (selection.selection != null ? HAS_SELECTION_MASK : 0)
                 | (selection.subSelections != null ? HAS_SUB_SELECTIONS_MASK : 0);
        }

        public void serialize(ColumnFilter selection, DataOutputPlus out, int version) throws IOException
        {
            out.writeByte(makeHeaderByte(selection));

            if (selection.selection != null)
            {
                Columns.serializer.serialize(selection.selection.statics, out);
                Columns.serializer.serialize(selection.selection.regulars, out);
            }

            if (selection.subSelections != null)
            {
                out.writeUnsignedVInt(selection.subSelections.size());
                for (ColumnSubselection subSel : selection.subSelections.values())
                    ColumnSubselection.serializer.serialize(subSel, out, version);
            }
        }

        public ColumnFilter deserialize(DataInputPlus in, int version, CFMetaData metadata) throws IOException
        {
            int header = in.readUnsignedByte();
            boolean isFetchAll = (header & IS_FETCH_ALL_MASK) != 0;
            boolean hasSelection = (header & HAS_SELECTION_MASK) != 0;
            boolean hasSubSelections = (header & HAS_SUB_SELECTIONS_MASK) != 0;

            PartitionColumns selection = null;
            if (hasSelection)
            {
                Columns statics = Columns.serializer.deserialize(in, metadata);
                Columns regulars = Columns.serializer.deserialize(in, metadata);
                selection = new PartitionColumns(statics, regulars);
            }

            SortedSetMultimap<ColumnIdentifier, ColumnSubselection> subSelections = null;
            if (hasSubSelections)
            {
                subSelections = TreeMultimap.create(Comparator.<ColumnIdentifier>naturalOrder(), Comparator.<ColumnSubselection>naturalOrder());
                int size = (int)in.readUnsignedVInt();
                for (int i = 0; i < size; i++)
                {
                    ColumnSubselection subSel = ColumnSubselection.serializer.deserialize(in, version, metadata);
                    subSelections.put(subSel.column().name, subSel);
                }
            }

            return new ColumnFilter(isFetchAll, isFetchAll ? metadata : null, selection, subSelections);
        }

        public long serializedSize(ColumnFilter selection, int version)
        {
            long size = 1; // header byte

            if (selection.selection != null)
            {
                size += Columns.serializer.serializedSize(selection.selection.statics);
                size += Columns.serializer.serializedSize(selection.selection.regulars);
            }

            if (selection.subSelections != null)
            {

                size += TypeSizes.sizeofUnsignedVInt(selection.subSelections.size());
                for (ColumnSubselection subSel : selection.subSelections.values())
                    size += ColumnSubselection.serializer.serializedSize(subSel, version);
            }

            return size;
        }
    }
}
