// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/layers/layer_iterator.h"

#include <vector>

#include "cc/layers/layer.h"
#include "cc/test/fake_layer_tree_host.h"
#include "cc/trees/layer_tree_host_common.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/transform.h"

using ::testing::Mock;
using ::testing::_;
using ::testing::AtLeast;
using ::testing::AnyNumber;

namespace cc {
namespace {

class TestLayer : public Layer {
 public:
  static scoped_refptr<TestLayer> Create() {
    return make_scoped_refptr(new TestLayer());
  }

  int count_representing_target_surface_;
  int count_representing_contributing_surface_;
  int count_representing_itself_;

  virtual bool DrawsContent() const OVERRIDE { return draws_content_; }
  void set_draws_content(bool draws_content) { draws_content_ = draws_content; }

 private:
  TestLayer() : Layer(), draws_content_(true) {
    SetBounds(gfx::Size(100, 100));
    SetPosition(gfx::Point());
  }
  virtual ~TestLayer() {}

  bool draws_content_;
};

#define EXPECT_COUNT(layer, target, contrib, itself)                           \
  EXPECT_EQ(target, layer->count_representing_target_surface_);                \
  EXPECT_EQ(contrib, layer->count_representing_contributing_surface_);         \
  EXPECT_EQ(itself, layer->count_representing_itself_);

typedef LayerIterator<Layer> FrontToBack;

void ResetCounts(RenderSurfaceLayerList* render_surface_layer_list) {
  for (unsigned surface_index = 0;
       surface_index < render_surface_layer_list->size();
       ++surface_index) {
    TestLayer* render_surface_layer = static_cast<TestLayer*>(
        render_surface_layer_list->at(surface_index));
    RenderSurface* render_surface = render_surface_layer->render_surface();

    render_surface_layer->count_representing_target_surface_ = -1;
    render_surface_layer->count_representing_contributing_surface_ = -1;
    render_surface_layer->count_representing_itself_ = -1;

    for (unsigned layer_index = 0;
         layer_index < render_surface->layer_list().size();
         ++layer_index) {
      TestLayer* layer = static_cast<TestLayer*>(
          render_surface->layer_list().at(layer_index).get());

      layer->count_representing_target_surface_ = -1;
      layer->count_representing_contributing_surface_ = -1;
      layer->count_representing_itself_ = -1;
    }
  }
}

void IterateFrontToBack(
    RenderSurfaceLayerList* render_surface_layer_list) {
  ResetCounts(render_surface_layer_list);
  int count = 0;
  for (FrontToBack it = FrontToBack::Begin(render_surface_layer_list);
       it != FrontToBack::End(render_surface_layer_list);
       ++it, ++count) {
    TestLayer* layer = static_cast<TestLayer*>(*it);
    if (it.represents_target_render_surface())
      layer->count_representing_target_surface_ = count;
    if (it.represents_contributing_render_surface())
      layer->count_representing_contributing_surface_ = count;
    if (it.represents_itself())
      layer->count_representing_itself_ = count;
  }
}

TEST(LayerIteratorTest, EmptyTree) {
  RenderSurfaceLayerList render_surface_layer_list;

  IterateFrontToBack(&render_surface_layer_list);
}

TEST(LayerIteratorTest, SimpleTree) {
  scoped_refptr<TestLayer> root_layer = TestLayer::Create();
  scoped_refptr<TestLayer> first = TestLayer::Create();
  scoped_refptr<TestLayer> second = TestLayer::Create();
  scoped_refptr<TestLayer> third = TestLayer::Create();
  scoped_refptr<TestLayer> fourth = TestLayer::Create();

  root_layer->AddChild(first);
  root_layer->AddChild(second);
  root_layer->AddChild(third);
  root_layer->AddChild(fourth);

  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
  scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
  host->SetRootLayer(root_layer);

  RenderSurfaceLayerList render_surface_layer_list;
  LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
      root_layer.get(), root_layer->bounds(), &render_surface_layer_list);
  LayerTreeHostCommon::CalculateDrawProperties(&inputs);

  IterateFrontToBack(&render_surface_layer_list);
  EXPECT_COUNT(root_layer, 5, -1, 4);
  EXPECT_COUNT(first, -1, -1, 3);
  EXPECT_COUNT(second, -1, -1, 2);
  EXPECT_COUNT(third, -1, -1, 1);
  EXPECT_COUNT(fourth, -1, -1, 0);
}

TEST(LayerIteratorTest, ComplexTree) {
  scoped_refptr<TestLayer> root_layer = TestLayer::Create();
  scoped_refptr<TestLayer> root1 = TestLayer::Create();
  scoped_refptr<TestLayer> root2 = TestLayer::Create();
  scoped_refptr<TestLayer> root3 = TestLayer::Create();
  scoped_refptr<TestLayer> root21 = TestLayer::Create();
  scoped_refptr<TestLayer> root22 = TestLayer::Create();
  scoped_refptr<TestLayer> root23 = TestLayer::Create();
  scoped_refptr<TestLayer> root221 = TestLayer::Create();
  scoped_refptr<TestLayer> root231 = TestLayer::Create();

  root_layer->AddChild(root1);
  root_layer->AddChild(root2);
  root_layer->AddChild(root3);
  root2->AddChild(root21);
  root2->AddChild(root22);
  root2->AddChild(root23);
  root22->AddChild(root221);
  root23->AddChild(root231);

  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
  scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
  host->SetRootLayer(root_layer);

  RenderSurfaceLayerList render_surface_layer_list;
  LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
      root_layer.get(), root_layer->bounds(), &render_surface_layer_list);
  LayerTreeHostCommon::CalculateDrawProperties(&inputs);

  IterateFrontToBack(&render_surface_layer_list);
  EXPECT_COUNT(root_layer, 9, -1, 8);
  EXPECT_COUNT(root1, -1, -1, 7);
  EXPECT_COUNT(root2, -1, -1, 6);
  EXPECT_COUNT(root21, -1, -1, 5);
  EXPECT_COUNT(root22, -1, -1, 4);
  EXPECT_COUNT(root221, -1, -1, 3);
  EXPECT_COUNT(root23, -1, -1, 2);
  EXPECT_COUNT(root231, -1, -1, 1);
  EXPECT_COUNT(root3, -1, -1, 0);
}

TEST(LayerIteratorTest, ComplexTreeMultiSurface) {
  scoped_refptr<TestLayer> root_layer = TestLayer::Create();
  scoped_refptr<TestLayer> root1 = TestLayer::Create();
  scoped_refptr<TestLayer> root2 = TestLayer::Create();
  scoped_refptr<TestLayer> root3 = TestLayer::Create();
  scoped_refptr<TestLayer> root21 = TestLayer::Create();
  scoped_refptr<TestLayer> root22 = TestLayer::Create();
  scoped_refptr<TestLayer> root23 = TestLayer::Create();
  scoped_refptr<TestLayer> root221 = TestLayer::Create();
  scoped_refptr<TestLayer> root231 = TestLayer::Create();

  root_layer->AddChild(root1);
  root_layer->AddChild(root2);
  root_layer->AddChild(root3);
  root2->set_draws_content(false);
  root2->SetOpacity(0.5f);
  root2->SetForceRenderSurface(true);  // Force the layer to own a new surface.
  root2->AddChild(root21);
  root2->AddChild(root22);
  root2->AddChild(root23);
  root22->SetOpacity(0.5f);
  root22->AddChild(root221);
  root23->SetOpacity(0.5f);
  root23->AddChild(root231);

  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
  scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
  host->SetRootLayer(root_layer);

  RenderSurfaceLayerList render_surface_layer_list;
  LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
      root_layer.get(), root_layer->bounds(), &render_surface_layer_list);
  LayerTreeHostCommon::CalculateDrawProperties(&inputs);

  IterateFrontToBack(&render_surface_layer_list);
  EXPECT_COUNT(root_layer, 14, -1, 13);
  EXPECT_COUNT(root1, -1, -1, 12);
  EXPECT_COUNT(root2, 10, 11, -1);
  EXPECT_COUNT(root21, -1, -1, 9);
  EXPECT_COUNT(root22, 7, 8, 6);
  EXPECT_COUNT(root221, -1, -1, 5);
  EXPECT_COUNT(root23, 3, 4, 2);
  EXPECT_COUNT(root231, -1, -1, 1);
  EXPECT_COUNT(root3, -1, -1, 0);
}

}  // namespace
}  // namespace cc
