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

#include "query_optimizer/rules/PushDownSemiAntiJoin.hpp"

#include <vector>

#include "query_optimizer/expressions/AttributeReference.hpp"
#include "query_optimizer/expressions/ExpressionUtil.hpp"
#include "query_optimizer/logical/HashJoin.hpp"
#include "query_optimizer/logical/Logical.hpp"
#include "query_optimizer/logical/PatternMatcher.hpp"

namespace quickstep {
namespace optimizer {

namespace E = ::quickstep::optimizer::expressions;
namespace L = ::quickstep::optimizer::logical;

L::LogicalPtr PushDownSemiAntiJoin::applyToNode(const L::LogicalPtr &input) {
  std::vector<L::LogicalPtr> new_children;
  bool has_changes = false;

  for (const L::LogicalPtr &child : input->children()) {
    L::HashJoinPtr hash_join;
    if (L::SomeHashJoin::MatchesWithConditionalCast(child, &hash_join)) {
      if (hash_join->join_type() == L::HashJoin::JoinType::kLeftSemiJoin ||
          hash_join->join_type() == L::HashJoin::JoinType::kLeftAntiJoin) {
        L::LogicalPtr new_child = pushDownSemiAntiJoin(hash_join);
        if (new_child != child) {
          has_changes = true;
        }
        new_children.push_back(new_child);
      }
    } else {
      new_children.push_back(child);
    }
  }

  if (has_changes) {
    return input->copyWithNewChildren(new_children);
  } else {
    return input;
  }
}

L::LogicalPtr PushDownSemiAntiJoin::pushDownSemiAntiJoin(
    const L::HashJoinPtr &semi_anti_join) {
  const L::LogicalPtr &left_input = semi_anti_join->left();
  std::vector<L::LogicalPtr> left_input_children = left_input->children();

  if (!left_input_children.empty()) {
    std::vector<L::LogicalPtr>::size_type last_input_index = left_input_children.size();
    // Cannot push down a Filter down the right child of LeftOuterJoin.
    L::HashJoinPtr hash_join;
    if (L::SomeHashJoin::MatchesWithConditionalCast(left_input, &hash_join) &&
        hash_join->join_type() == L::HashJoin::JoinType::kLeftOuterJoin) {
      DCHECK_EQ(2u, left_input_children.size());
      last_input_index = 1u;
    }

    std::vector<L::LogicalPtr>::size_type input_index = 0;
    while (input_index < last_input_index) {
      if (SubsetOfExpressions(semi_anti_join->left_join_attributes(),
                              left_input_children[input_index]->getOutputAttributes())) {
        break;
      }
      ++input_index;
    }

    if (input_index < last_input_index &&
        semi_anti_join->residual_predicate() != nullptr) {
      const std::vector<E::AttributeReferencePtr> input_child_output_attributes =
          left_input_children[input_index]->getOutputAttributes();
      const std::vector<E::AttributeReferencePtr> right_input_output_attributes =
          semi_anti_join->right()->getOutputAttributes();
      E::UnorderedAttributeSet visible_attribute_set(input_child_output_attributes.begin(),
                                                     input_child_output_attributes.end());
      visible_attribute_set.insert(right_input_output_attributes.begin(),
                                   right_input_output_attributes.end());

      const std::vector<E::AttributeReferencePtr> referenced_attrs_in_residual =
          E::GetAttributeReferencesWithinScope(
              semi_anti_join->residual_predicate()->getReferencedAttributes(),
              E::AttributeReferenceScope::kLocal);
      for (const E::AttributeReferencePtr &referenced_attr : referenced_attrs_in_residual) {
        if (visible_attribute_set.find(referenced_attr) == visible_attribute_set.end()) {
          input_index = last_input_index;
          break;
        }
      }
    }

    if (input_index < last_input_index) {
      left_input_children[input_index] =
          semi_anti_join->copyWithNewChildren({left_input_children[input_index],
                                               semi_anti_join->right()});
      return left_input->copyWithNewChildren(left_input_children);
    }
  }

  return semi_anti_join;
}

}  // namespace optimizer
}  // namespace quickstep
