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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.phoenix.compile.ColumnResolver;
import org.apache.phoenix.expression.function.CountAggregateFunction;
import org.apache.phoenix.jdbc.PhoenixStatement.Operation;
import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction;
import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo;

/**
 * 
 * Top level node representing a SQL statement
 *
 * 
 * @since 0.1
 */
public class SelectStatement implements FilterableStatement {
    public static final SelectStatement SELECT_STAR =
            new SelectStatement(
                    null, null, false,
                    Arrays.asList(),
                    null, Collections.<ParseNode>emptyList(),
                    null, Collections.<OrderByNode>emptyList(),
                    null, null, 0, false, false, Collections.<SelectStatement>emptyList(), new HashMap<String, UDFParseNode>(1));
    public static final SelectStatement SELECT_ONE =
            new SelectStatement(
                    null, null, false, 
                    Collections.<AliasedNode>singletonList(new AliasedNode(null, LiteralParseNode.ONE)),
                    null, Collections.<ParseNode>emptyList(),
                    null, Collections.<OrderByNode>emptyList(),
                    null, null, 0, false, false, Collections.<SelectStatement>emptyList(), new HashMap<String, UDFParseNode>(1));
    public static final SelectStatement COUNT_ONE =
            new SelectStatement(
                    null, null, false,
                    Collections.<AliasedNode>singletonList(
                    new AliasedNode(null, 
                        new AggregateFunctionParseNode(
                                CountAggregateFunction.NORMALIZED_NAME, 
                                LiteralParseNode.STAR, 
                                new BuiltInFunctionInfo(CountAggregateFunction.class, CountAggregateFunction.class.getAnnotation(BuiltInFunction.class))))),
                    null, Collections.<ParseNode>emptyList(), 
                    null, Collections.<OrderByNode>emptyList(), 
                    null,null, 0, true, false, Collections.<SelectStatement>emptyList(), new HashMap<String, UDFParseNode>(1));
    public static SelectStatement create(SelectStatement select, HintNode hint) {
        if (select.getHint() == hint || hint.isEmpty()) {
            return select;
        }
        return new SelectStatement(select.getFrom(), hint, select.isDistinct(), 
                select.getSelect(), select.getWhere(), select.getGroupBy(), select.getHaving(), 
                select.getOrderBy(), select.getLimit(), select.getOffset(), select.getBindCount(), select.isAggregate(), select.hasSequence(), select.getSelects(), select.getUdfParseNodes());
    }

    public static SelectStatement create(SelectStatement select, TableNode tableNode, List<AliasedNode> selects) {
        return new SelectStatement(tableNode, select.getHint(), select.isDistinct(),
                selects, select.getWhere(), select.getGroupBy(), select.getHaving(),
                select.getOrderBy(), select.getLimit(), select.getOffset(), select.getBindCount(), select.isAggregate(), select.hasSequence(), select.getSelects(), select.getUdfParseNodes());
    }

    public SelectStatement combine(ParseNode where) {
        if (where == null) {
            return this;
        }
        if (this.getWhere() != null) {
            where = new AndParseNode(Arrays.asList(this.getWhere(), where));
        }
        return new SelectStatement(this.getFrom(), this.getHint(), this.isDistinct(), 
                this.getSelect(), where, this.getGroupBy(), this.getHaving(), 
                this.getOrderBy(), this.getLimit(), this.getOffset(), this.getBindCount(), this.isAggregate(), this.hasSequence(), this.selects, this.udfParseNodes);
    }
    
    public static SelectStatement create(SelectStatement select, List<AliasedNode> selects) {
        return new SelectStatement(select.getFrom(), select.getHint(), select.isDistinct(), 
                selects, select.getWhere(), select.getGroupBy(), select.getHaving(), 
                select.getOrderBy(), select.getLimit(), select.getOffset(), select.getBindCount(), select.isAggregate(), select.hasSequence(), select.getSelects(), select.getUdfParseNodes());
    }
    
    // Copy constructor for sub select statements in a union
    public static SelectStatement create(SelectStatement select, List<OrderByNode> orderBy, LimitNode limit,
            OffsetNode offset, boolean isAggregate) {
        return new SelectStatement(select.getFrom(), select.getHint(), select.isDistinct(), select.getSelect(),
                select.getWhere(), select.getGroupBy(), select.getHaving(), orderBy, limit, offset,
                select.getBindCount(), isAggregate, select.hasSequence(), select.getSelects(),
                select.getUdfParseNodes());
    }

    private final TableNode fromTable;
    private final HintNode hint;
    private final boolean isDistinct;
    private final List<AliasedNode> select;
    private final ParseNode where;
    private final List<ParseNode> groupBy;
    private final ParseNode having;
    private final List<OrderByNode> orderBy;
    private final LimitNode limit;
    private final int bindCount;
    private final boolean isAggregate;
    private final boolean hasSequence;
    private final boolean hasWildcard;
    private final List<SelectStatement> selects = new ArrayList<SelectStatement>();
    private final Map<String, UDFParseNode> udfParseNodes;
    private final OffsetNode offset;
    
    @Override
    public final String toString() {
        StringBuilder buf = new StringBuilder();
        toSQL(null,buf);
        return buf.toString();
    }

    public void toSQL(ColumnResolver resolver, StringBuilder buf) {
        buf.append("SELECT ");
        if (hint != null) buf.append(hint);
        if (isDistinct) buf.append("DISTINCT ");
        for (AliasedNode selectNode : select) {
            selectNode.toSQL(resolver, buf);
            buf.append(',');
        }
        buf.setLength(buf.length()-1);
        if (fromTable != null) {
            buf.append(" FROM ");
            fromTable.toSQL(resolver, buf);
        }
        if (where != null) {
            buf.append(" WHERE ");
            where.toSQL(resolver, buf);
        }
        if (!groupBy.isEmpty()) {
            buf.append(" GROUP BY ");
            for (ParseNode node : groupBy) {
                node.toSQL(resolver, buf);
                buf.append(',');
            }
            buf.setLength(buf.length()-1);
        }
        if (having != null) {
            buf.append(" HAVING ");
            having.toSQL(resolver, buf);            
        }
        if (!orderBy.isEmpty()) {
            buf.append(" ORDER BY ");
            for (OrderByNode node : orderBy) {
                node.toSQL(resolver, buf);
                buf.append(',');
            }
            buf.setLength(buf.length()-1);
        }
        if (limit != null) {
            buf.append(" LIMIT " + limit.toString());
        }
        if (offset != null) {
            buf.append(" OFFSET " + offset.toString());
        }
    }    

    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((fromTable == null) ? 0 : fromTable.hashCode());
        result = prime * result + ((groupBy == null) ? 0 : groupBy.hashCode());
        result = prime * result + ((having == null) ? 0 : having.hashCode());
        result = prime * result + ((hint == null) ? 0 : hint.hashCode());
        result = prime * result + (isDistinct ? 1231 : 1237);
        result = prime * result + ((limit == null) ? 0 : limit.hashCode());
        result = prime * result + ((orderBy == null) ? 0 : orderBy.hashCode());
        result = prime * result + ((select == null) ? 0 : select.hashCode());
        result = prime * result + ((where == null) ? 0 : where.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        SelectStatement other = (SelectStatement)obj;
        if (fromTable == null) {
            if (other.fromTable != null) return false;
        } else if (!fromTable.equals(other.fromTable)) return false;
        if (groupBy == null) {
            if (other.groupBy != null) return false;
        } else if (!groupBy.equals(other.groupBy)) return false;
        if (having == null) {
            if (other.having != null) return false;
        } else if (!having.equals(other.having)) return false;
        if (hint == null) {
            if (other.hint != null) return false;
        } else if (!hint.equals(other.hint)) return false;
        if (isDistinct != other.isDistinct) return false;
        if (limit == null) {
            if (other.limit != null) return false;
        } else if (!limit.equals(other.limit)) return false;
        if (orderBy == null) {
            if (other.orderBy != null) return false;
        } else if (!orderBy.equals(other.orderBy)) return false;
        if (select == null) {
            if (other.select != null) return false;
        } else if (!select.equals(other.select)) return false;
        if (where == null) {
            if (other.where != null) return false;
        } else if (!where.equals(other.where)) return false;
        return true;
    }

    // Count constant expressions
    private static int countConstants(List<ParseNode> nodes) {
        int count = 0;
        for (int i = 0; i < nodes.size(); i++) {
            if (nodes.get(i).isStateless()) {
                count++;
            }
        }
        return count;
    }
    
    protected SelectStatement(TableNode from, HintNode hint, boolean isDistinct, List<AliasedNode> select,
            ParseNode where, List<ParseNode> groupBy, ParseNode having, List<OrderByNode> orderBy, LimitNode limit,
            OffsetNode offset, int bindCount, boolean isAggregate, boolean hasSequence, List<SelectStatement> selects,
            Map<String, UDFParseNode> udfParseNodes) {
        this.fromTable = from;
        this.hint = hint == null ? HintNode.EMPTY_HINT_NODE : hint;
        this.isDistinct = isDistinct;
        this.select = Collections.unmodifiableList(select);
        this.where = where;
        this.groupBy = Collections.unmodifiableList(groupBy);
        this.having = having;
        this.orderBy = Collections.unmodifiableList(orderBy);
        this.limit = limit;
        this.offset = offset;
        this.bindCount = bindCount;
        this.isAggregate = isAggregate || groupBy.size() != countConstants(groupBy) || this.having != null;
        this.hasSequence = hasSequence;
        boolean hasWildcard = false;
        for (AliasedNode aliasedNode : select) {
            ParseNode node = aliasedNode.getNode();
            if (node instanceof WildcardParseNode || node instanceof TableWildcardParseNode || node instanceof FamilyWildcardParseNode) {
                hasWildcard = true;
                break;
            }
        }
        this.hasWildcard = hasWildcard;
        if (!selects.isEmpty()) {
            this.selects.addAll(selects);
        }
        this.udfParseNodes = udfParseNodes;
    }
    
    @Override
    public boolean isDistinct() {
        return isDistinct;
    }
    
    @Override
    public LimitNode getLimit() {
        return limit;
    }
    
    /**
     *  This method should not be called during the early stage 
     *  of the plan preparation phase since fromTable might not 
     *  be ConcreteTableNode at that time(e.g., JoinTableNode).
     *  
     *  By the time getTableSamplingRate method is called, 
     *  each select statements should have exactly one ConcreteTableNode,
     *  with its corresponding sampling rate associate with it.
     */
    @Override
    public Double getTableSamplingRate(){
    	if(fromTable==null || !(fromTable instanceof ConcreteTableNode)) return null;
    	return ((ConcreteTableNode)fromTable).getTableSamplingRate();
    }
    
    @Override
    public int getBindCount() {
        return bindCount;
    }
    
    public TableNode getFrom() {
        return fromTable;
    }
    
    @Override
    public HintNode getHint() {
        return hint;
    }
    
    public List<AliasedNode> getSelect() {
        return select;
    }
    /**
     * Gets the where condition, or null if none.
     */
    @Override
    public ParseNode getWhere() {
        return where;
    }
    
    /**
     * Gets the group-by, containing at least 1 element, or empty list, if none.
     */
    public List<ParseNode> getGroupBy() {
        return groupBy;
    }
    
    public ParseNode getHaving() {
        return having;
    }
    
    /**
     * Gets the order-by, containing at least 1 element, or null, if none.
     */
    @Override
    public List<OrderByNode> getOrderBy() {
        return orderBy;
    }

    @Override
    public boolean isAggregate() {
        return isAggregate;
    }

    public boolean hasSequence() {
        return hasSequence;
    }

    @Override
    public Operation getOperation() {
        return Operation.QUERY;
    }

    public boolean isJoin() {
        return fromTable != null && fromTable instanceof JoinTableNode;
    }
    
    public SelectStatement getInnerSelectStatement() {
        if (fromTable == null || !(fromTable instanceof DerivedTableNode))
            return null;
        
        return ((DerivedTableNode) fromTable).getSelect();
    }

    public boolean isUnion() {
        return !getSelects().isEmpty();
    }

    public List<SelectStatement> getSelects() {
        return selects;
    }
    
    public boolean hasWildcard() {
        return hasWildcard;
    }

    public Map<String, UDFParseNode> getUdfParseNodes() {
        return udfParseNodes;
    }

    @Override
    public OffsetNode getOffset() {
        return offset;
    }

}
