/*
 * 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
