// 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 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::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 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 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::Node* node) {
  auto* filter_node =
      base::polymorphic_downcast<render_tree::FilterNode*>(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
