// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed 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 "cobalt/renderer/rasterizer/common/find_node.h"

#include "base/optional.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/render_tree/animations/animate_node.h"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace common {

class FinderNodeVisitor : public render_tree::NodeVisitor {
 public:
  FinderNodeVisitor(NodeFilterFunction<render_tree::Node> filter_function,
                    base::Optional<NodeReplaceFunction> replace_function)
      : filter_function_(filter_function),
        replace_function_(replace_function) {}

  void Visit(render_tree::animations::AnimateNode* animate) override {
    VisitNode(animate);
  }
  void Visit(render_tree::ClearRectNode* clear_rect_node) override {
    VisitNode(clear_rect_node);
  }
  void Visit(render_tree::CompositionNode* composition_node) override {
    VisitNode(composition_node);
  }
  void Visit(render_tree::FilterNode* filter_node) override {
    VisitNode(filter_node);
  }
  void Visit(render_tree::ImageNode* image_node) override {
    VisitNode(image_node);
  }
  void Visit(render_tree::LottieNode* lottie_node) override {
    VisitNode(lottie_node);
  }
  void Visit(render_tree::MatrixTransform3DNode* transform_3d_node) override {
    VisitNode(transform_3d_node);
  }
  void Visit(render_tree::MatrixTransformNode* transform_node) override {
    VisitNode(transform_node);
  }
  void Visit(render_tree::PunchThroughVideoNode* punch_through) override {
    VisitNode(punch_through);
  }
  void Visit(render_tree::RectNode* rect) override { VisitNode(rect); }
  void Visit(render_tree::RectShadowNode* rect) override { VisitNode(rect); }
  void Visit(render_tree::TextNode* text) override { VisitNode(text); }

  virtual ~FinderNodeVisitor() {}

  scoped_refptr<render_tree::Node> GetFoundNode() const { return found_node_; }

  scoped_refptr<render_tree::Node> GetReplaceWithNode() {
    return replace_with_;
  }

 private:
  template <typename T>
  void VisitNode(T* node) {
    if (filter_function_.Run(static_cast<render_tree::Node*>(node))) {
      found_node_ = node;
      if (replace_function_) {
        replace_with_ = replace_function_->Run(node);
      }
    } else {
      VisitNodeChildren(node);
    }
  }

  template <typename T>
  typename base::enable_if<!render_tree::ChildIterator<T>::has_children>::type
  VisitNodeChildren(T* node) {
    // No children to visit.
  }

  template <typename T>
  typename base::enable_if<render_tree::ChildIterator<T>::has_children>::type
  VisitNodeChildren(T* node) {
    render_tree::ChildIterator<T> child_iterator(node);
    while (render_tree::Node* child = child_iterator.GetCurrent()) {
      child->Accept(this);
      if (found_node_) {
        if (replace_with_) {
          child_iterator.ReplaceCurrent(replace_with_);
        }
        break;
      }
      child_iterator.Next();
    }
    if (replace_with_) {
      replace_with_ = new T(child_iterator.TakeReplacedChildrenBuilder());
    }
  }

  NodeFilterFunction<render_tree::Node> filter_function_;
  base::Optional<NodeReplaceFunction> replace_function_;

  scoped_refptr<render_tree::Node> found_node_;
  scoped_refptr<render_tree::Node> replace_with_;
};

template <>
NodeSearchResult<render_tree::Node> FindNode<render_tree::Node>(
    const scoped_refptr<render_tree::Node>& tree,
    NodeFilterFunction<render_tree::Node> filter_function,
    base::Optional<NodeReplaceFunction> replace_function) {
  FinderNodeVisitor visitor(filter_function, replace_function);
  tree->Accept(&visitor);

  NodeSearchResult<render_tree::Node> result;
  result.found_node = visitor.GetFoundNode();
  result.replaced_tree = visitor.GetReplaceWithNode();

  if (result.replaced_tree.get() == NULL) {
    result.replaced_tree = tree;
  }
  return result;
}

bool HasMapToMesh(render_tree::FilterNode* filter_node) {
  return static_cast<bool>(filter_node->data().map_to_mesh_filter);
}

render_tree::Node* ReplaceWithEmptyCompositionNode(
    render_tree::Node* filter_node) {
  return new render_tree::CompositionNode(
      render_tree::CompositionNode::Builder());
}

}  // namespace common
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt
