module SQLTree::Node
  
  class SelectQuery < Base
  
    attr_accessor :distinct, :select, :from, :where, :group_by, :having, :order_by, :limit
  
    def initialize
      @distinct = false
      @select   = []
    end
  
    def to_sql
      raise "At least one SELECT expression is required" if self.select.empty?
      sql = (self.distinct) ? "SELECT DISTINCT " : "SELECT "
      sql << select.map { |s| s.to_sql }.join(', ')
      sql << " FROM " << from.map { |f| f.to_sql }.join(', ')
      sql << " WHERE " << where.to_sql if where
      return sql
    end
  
    # Uses the provided initialized parser to parse a SELECT query.
    def self.parse(tokens)
      select_node = self.new
      tokens.consume(SQLTree::Token::SELECT)

      if tokens.peek == SQLTree::Token::DISTINCT
        tokens.consume(SQLTree::Token::DISTINCT)
        select_node.distinct = true
      end

      select_node.select = self.parse_select_clause(tokens)
      select_node.from   = self.parse_from_clause(tokens)   if tokens.peek == SQLTree::Token::FROM
      select_node.where  = self.parse_where_clause(tokens)  if tokens.peek == SQLTree::Token::WHERE

      return select_node
    end
    
    def self.parse_select_clause(tokens)
      expressions = [SQLTree::Node::SelectExpression.parse(tokens)]
      while tokens.peek == SQLTree::Token::COMMA
        tokens.consume(SQLTree::Token::COMMA)
        expressions << SQLTree::Node::SelectExpression.parse(tokens)
      end
      return expressions
    end
    
    def self.parse_from_clause(tokens)
      tokens.consume(SQLTree::Token::FROM)
      sources = [SQLTree::Node::Source.parse(tokens)]
      while tokens.peek == SQLTree::Token::COMMA
        tokens.consume(SQLTree::Token::COMMA)
        sources << SQLTree::Node::Source.parse(tokens)
      end
      return sources
    end
    
    def self.parse_where_clause(tokens)
      tokens.consume(SQLTree::Token::WHERE)
      Expression.parse(tokens)
    end

    def self.parse_group_clause(tokens)
      # TODO: implement me
    end

    def self.parse_having_clause(tokens)
      # TODO: implement me
    end
    
    def self.parse_order_clause(tokens)
      # TODO: implement me
    end

    def self.parse_limit_clause(tokens)
      # TODO: implement me
    end
  end
end