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

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import com.google.common.collect.Sets;
import com.google.common.primitives.Longs;

import com.datastax.driver.core.BatchStatement;
import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.SimpleStatement;
import com.datastax.driver.core.Statement;
import org.apache.cassandra.fql.FullQueryLogger;
import org.apache.cassandra.cql3.QueryOptions;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.QueryState;
import org.apache.cassandra.utils.binlog.BinLog;

public abstract class FQLQuery implements Comparable<FQLQuery>
{
    public final long queryStartTime;
    public final QueryOptions queryOptions;
    public final int protocolVersion;
    public final QueryState queryState;

    public FQLQuery(String keyspace, int protocolVersion, QueryOptions queryOptions, long queryStartTime, long generatedTimestamp, int generatedNowInSeconds)
    {
        this.queryStartTime = queryStartTime;
        this.queryOptions = queryOptions;
        this.protocolVersion = protocolVersion;
        this.queryState = queryState(keyspace, generatedTimestamp, generatedNowInSeconds);
    }

    public abstract Statement toStatement();

    /**
     * used when storing the queries executed
     */
    public abstract BinLog.ReleaseableWriteMarshallable toMarshallable();

    public String keyspace()
    {
        return queryState.getClientState().getRawKeyspace();
    }

    private QueryState queryState(String keyspace, long generatedTimestamp, int generatedNowInSeconds)
    {
        ClientState clientState = keyspace != null ? ClientState.forInternalCalls(keyspace) : ClientState.forInternalCalls();
        return new QueryState(clientState, generatedTimestamp, generatedNowInSeconds);
    }

    public boolean equals(Object o)
    {
        if (this == o) return true;
        if (!(o instanceof FQLQuery)) return false;
        FQLQuery fqlQuery = (FQLQuery) o;
        return queryStartTime == fqlQuery.queryStartTime &&
               protocolVersion == fqlQuery.protocolVersion &&
               queryState.getTimestamp() == fqlQuery.queryState.getTimestamp() &&
               Objects.equals(queryState.getClientState().getRawKeyspace(), fqlQuery.queryState.getClientState().getRawKeyspace()) &&
               Objects.equals(queryOptions.getValues(), fqlQuery.queryOptions.getValues());
    }

    public int hashCode()
    {
        return Objects.hash(queryStartTime, queryOptions, protocolVersion, queryState.getClientState().getRawKeyspace());
    }

    public int compareTo(FQLQuery other)
    {
        return Longs.compare(queryStartTime, other.queryStartTime);
    }

    public String toString()
    {
        return "FQLQuery{" +
               "queryStartTime=" + queryStartTime +
               ", protocolVersion=" + protocolVersion +
               ", queryState='" + queryState + '\'' +
               '}';
    }

    public abstract boolean isDDLStatement();

    public static class Single extends FQLQuery
    {
        private static final Set<String> DDL_STATEMENTS = Sets.newHashSet("CREATE", "ALTER", "DROP");

        public final String query;
        public final List<ByteBuffer> values;

        public Single(String keyspace, int protocolVersion, QueryOptions queryOptions, long queryStartTime, long generatedTimestamp, int generatedNowInSeconds, String queryString, List<ByteBuffer> values)
        {
            super(keyspace, protocolVersion, queryOptions, queryStartTime, generatedTimestamp, generatedNowInSeconds);
            this.query = queryString;
            this.values = values;
        }

        @Override
        public String toString()
        {
            return String.format("%s: Query: [%s], valuecount : %d",
                                 super.toString(),
                                 query,
                                 values.size());
        }

        public boolean isDDLStatement()
        {
            for (final String ddlStmt : DDL_STATEMENTS)
            {
                if (this.query.startsWith(ddlStmt))
                {
                    return true;
                }
            }
            return false;
        }

        public Statement toStatement()
        {
            SimpleStatement ss = new SimpleStatement(query, values.toArray());
            ss.setConsistencyLevel(ConsistencyLevel.valueOf(queryOptions.getConsistency().name()));
            ss.setDefaultTimestamp(queryOptions.getTimestamp(queryState));
            return ss;
        }

        public BinLog.ReleaseableWriteMarshallable toMarshallable()
        {

            return new FullQueryLogger.Query(query, queryOptions, queryState, queryStartTime);
        }

        public int compareTo(FQLQuery other)
        {
            int cmp = super.compareTo(other);

            if (cmp == 0)
            {
                if (other instanceof Batch)
                    return -1;

                Single singleQuery = (Single) other;

                cmp = query.compareTo(singleQuery.query);
                if (cmp == 0)
                {
                    if (values.size() != singleQuery.values.size())
                        return values.size() - singleQuery.values.size();
                    for (int i = 0; i < values.size(); i++)
                    {
                        cmp = values.get(i).compareTo(singleQuery.values.get(i));
                        if (cmp != 0)
                            return cmp;
                    }
                }
            }
            return cmp;
        }

        public boolean equals(Object o)
        {
            if (this == o) return true;
            if (!(o instanceof Single)) return false;
            if (!super.equals(o)) return false;
            Single single = (Single) o;
            return Objects.equals(query, single.query) &&
                   Objects.equals(values, single.values);
        }

        public int hashCode()
        {
            return Objects.hash(super.hashCode(), query, values);
        }
    }

    public static class Batch extends FQLQuery
    {
        public final BatchStatement.Type batchType;
        public final List<Single> queries;

        public Batch(String keyspace, int protocolVersion, QueryOptions queryOptions, long queryStartTime, long generatedTimestamp, int generatedNowInSeconds, BatchStatement.Type batchType, List<String> queries, List<List<ByteBuffer>> values)
        {
            super(keyspace, protocolVersion, queryOptions, queryStartTime, generatedTimestamp, generatedNowInSeconds);
            this.batchType = batchType;
            this.queries = new ArrayList<>(queries.size());
            for (int i = 0; i < queries.size(); i++)
                this.queries.add(new Single(keyspace, protocolVersion, queryOptions, queryStartTime, generatedTimestamp, generatedNowInSeconds, queries.get(i), values.get(i)));
        }

        public Statement toStatement()
        {
            BatchStatement bs = new BatchStatement(batchType);
            for (Single query : queries)
                bs.add(query.toStatement());
            bs.setConsistencyLevel(ConsistencyLevel.valueOf(queryOptions.getConsistency().name()));
            bs.setDefaultTimestamp(queryOptions.getTimestamp(queryState));
            return bs;
        }

        public int compareTo(FQLQuery other)
        {
            int cmp = super.compareTo(other);

            if (cmp == 0)
            {
                if (other instanceof Single)
                    return 1;

                Batch otherBatch = (Batch) other;
                if (queries.size() != otherBatch.queries.size())
                    return queries.size() - otherBatch.queries.size();
                for (int i = 0; i < queries.size(); i++)
                {
                    cmp = queries.get(i).compareTo(otherBatch.queries.get(i));
                    if (cmp != 0)
                        return cmp;
                }
            }
            return cmp;
        }

        public BinLog.ReleaseableWriteMarshallable toMarshallable()
        {
            List<String> queryStrings = new ArrayList<>();
            List<List<ByteBuffer>> values = new ArrayList<>();
            for (Single q : queries)
            {
                queryStrings.add(q.query);
                values.add(q.values);
            }
            return new FullQueryLogger.Batch(org.apache.cassandra.cql3.statements.BatchStatement.Type.valueOf(batchType.name()), queryStrings, values, queryOptions, queryState, queryStartTime);
        }

        public String toString()
        {
            StringBuilder sb = new StringBuilder(super.toString()).append(" batch: ").append(batchType).append(':');
            for (Single q : queries)
                sb.append(q.toString()).append(',');
            sb.append("end batch");
            return sb.toString();
        }

        public boolean isDDLStatement()
        {
            return false;
        }

        public boolean equals(Object o)
        {
            if (this == o) return true;
            if (!(o instanceof Batch)) return false;
            if (!super.equals(o)) return false;
            Batch batch = (Batch) o;
            return batchType == batch.batchType &&
                   Objects.equals(queries, batch.queries);
        }

        public int hashCode()
        {
            return Objects.hash(super.hashCode(), batchType, queries);
        }
    }
}
