/*
 * 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.
 */
#ifndef READER_EXPRESSION_H
#define READER_EXPRESSION_H

#include <string>
#include <vector>

#include "common/db_common.h"
#include "common/path.h"
#include "filter/filter.h"

namespace storage {

class Filter;

enum ExpressionType {
    AND_EXPR,
    OR_EXPR,
    SERIES_EXPR,
    GLOBALTIME_EXPR,
    INVALID_EXPR
};

struct Expression {
    ExpressionType type_;
    Expression *left_;
    Expression *right_;
    Filter *filter_;
    Path series_path_;

    Expression(ExpressionType t)
        : type_(t),
          left_(nullptr),
          right_(nullptr),
          filter_(nullptr),
          series_path_() {}
    Expression(ExpressionType t, Expression *l, Expression *r)
        : type_(t), left_(l), right_(r), filter_(nullptr), series_path_() {}
    Expression(ExpressionType t, Filter *f)
        : type_(t),
          left_(nullptr),
          right_(nullptr),
          filter_(f),
          series_path_() {}
    Expression(ExpressionType t, const Path &path, Filter *f)
        : type_(t),
          left_(nullptr),
          right_(nullptr),
          filter_(f),
          series_path_(path) {}
    void destroy() {
        if (filter_ != nullptr) {
            delete filter_;
            filter_ = nullptr;
        } 
        if (left_ != nullptr) {
            delete left_;
            left_ = nullptr;
        }
        if (right_ != nullptr) {
            delete right_;
            right_ = nullptr;
        }
    }
    ~Expression() { destroy(); }
};

class QueryExpression {
   public:
    QueryExpression() : has_filter_(false), expression_(nullptr) {}
    ~QueryExpression() { destory(); }

    static QueryExpression *create(const std::vector<Path> &selected_series,
                                   Expression *expression) {
        QueryExpression *ret = new QueryExpression();
        ret->selected_series_ = selected_series;
        ret->expression_ = expression;
        ret->has_filter_ = (expression != nullptr);
        return ret;
    }
    static void destory(QueryExpression *expr) {
        if (expr) {
            delete expr;
        }
    }
    FORCE_INLINE void set_select_series(
        const std::vector<Path> &selected_series) {
        selected_series_ = selected_series;
    }
    FORCE_INLINE void add_select_series(const Path &path) {
        selected_series_.push_back(path);
    }
    FORCE_INLINE void set_expression(Expression *expression) {
        if (expression) {
            expression_ = expression;
            has_filter_ = true;
        }
    }
    Expression *optimize(Expression *expression,
                         std::vector<Path> &series_paths);
    void destory();

   private:
    Expression *combine_two_global_time_filter(Expression *left,
                                               Expression *right,
                                               ExpressionType type);
    Expression *handle_one_global_time_filter(
        Expression *left, Expression *expression,
        std::vector<Path> &selected_series, ExpressionType type);
    void add_time_filter_to_query_filter(Filter *time_filter,
                                         Expression *expression);
    void add_time_filter_to_series_filter(Filter *time_filter,
                                          Expression *single_series_expr);
    Expression *push_global_time_filter_to_all_series(
        Expression *time_filter, std::vector<Path> &selected_series);
    Expression *merge_second_tree_to_first_tree(Expression *left_expression,
                                                Expression *right_expression);
    bool update_filter_with_or(Expression *expression, Filter *filter,
                               Path &path);

   public:
    bool has_filter_;
    std::vector<Path> selected_series_;
    std::vector<common::TSDataType> data_types_;
    Expression *expression_;
    std::vector<Expression *> my_exprs_;
    std::vector<Filter *> my_filters_;
};

}  // namespace storage

#endif  // READER_EXPRESSION_H
