/*
 * Copyright 2015 Google Inc. 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 "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "cobalt/base/clock.h"
#include "cobalt/css_parser/parser.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_parser.h"
#include "cobalt/dom/dom_stat_tracker.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/html_body_element.h"
#include "cobalt/dom/html_collection.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom_parser/parser.h"
#include "cobalt/loader/image/image_cache.h"
#include "cobalt/loader/loader.h"
#include "cobalt/render_tree/resource_provider_stub.h"
#include "cobalt/script/fake_script_runner.h"
#include "cobalt/webdriver/algorithms.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace webdriver {
namespace {

const uint32 kImageCacheCapacity = 32U * 1024 * 1024;

void OnError(const std::string& error) { DLOG(ERROR) << error; }

class IsDisplayedTest : public ::testing::Test, public dom::DocumentObserver {
 protected:
  IsDisplayedTest()
      : fetcher_factory_(NULL /* network_module */),
        css_parser_(css_parser::Parser::Create()),
        dom_parser_(new dom_parser::Parser()),
        resource_provider_stub_(new render_tree::ResourceProviderStub()),
        image_cache_(loader::image::CreateImageCache(
            "WebdriverTest.ImageCache", kImageCacheCapacity,
            resource_provider_stub_.get(), &fetcher_factory_)),
        dom_stat_tracker_(new dom::DomStatTracker("IsDisplayedTest")),
        html_element_context_(
            &fetcher_factory_, css_parser_.get(), dom_parser_.get(),
            NULL /* web_media_player_factory */, &script_runner_,
            NULL /* media_source_registry */, resource_provider_stub_.get(),
            image_cache_.get(), NULL /* remote_font_cache */,
            dom_stat_tracker_.get(), "" /* language */) {}

  void SetUp() OVERRIDE {
    // Load the document in a nested message loop.
    GURL url("file:///cobalt/webdriver_test/displayed_test.html");
    dom::Document::Options options(url);
    options.navigation_start_clock = new base::SystemMonotonicClock();
    options.viewport_size = math::Size(1920, 1080);

    document_ = new dom::Document(&html_element_context_, options);
    document_->AddObserver(this);
    document_loader_.reset(new loader::Loader(
        base::Bind(&loader::FetcherFactory::CreateFetcher,
                   base::Unretained(&fetcher_factory_), url),
        dom_parser_->ParseDocumentAsync(document_,
                                        base::SourceLocation(url.spec(), 1, 1)),
        base::Bind(&OnError)));

    nested_loop_.Run();
  }

  // dom::DocumentObserver functions
  void OnLoad() OVERRIDE { nested_loop_.Quit(); }
  void OnMutation() OVERRIDE {}

  script::FakeScriptRunner script_runner_;
  loader::FetcherFactory fetcher_factory_;
  scoped_ptr<css_parser::Parser> css_parser_;
  scoped_ptr<dom_parser::Parser> dom_parser_;
  scoped_ptr<render_tree::ResourceProviderStub> resource_provider_stub_;
  scoped_ptr<loader::image::ImageCache> image_cache_;
  scoped_ptr<dom::DomStatTracker> dom_stat_tracker_;
  dom::HTMLElementContext html_element_context_;
  scoped_refptr<dom::Document> document_;
  scoped_ptr<loader::Loader> document_loader_;

  // A nested message loop needs a non-nested message loop to exist.
  MessageLoop message_loop_;

  // Nested message loop on which the document loading will occur.
  base::RunLoop nested_loop_;
};

}  // namespace

TEST_F(IsDisplayedTest, BodyIsDisplayed) {
  EXPECT_TRUE(algorithms::IsDisplayed(document_->body().get()));
  document_->body()->style()->set_display("none", NULL);
  EXPECT_TRUE(algorithms::IsDisplayed(document_->body().get()));
}

TEST_F(IsDisplayedTest, ElementIsShown) {
  // No style set.
  EXPECT_TRUE(
      algorithms::IsDisplayed(document_->GetElementById("displayed").get()));
  // display: none
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("none").get()));
  // visiblity: hidden
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("hidden").get()));
}

TEST_F(IsDisplayedTest, HiddenByParentDisplayStyle) {
  // display: none
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("hiddenparent").get()));
  // No style set, but is a child of hiddenparent.
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("hiddenchild").get()));
  // No style set, but is a child of hiddenchild.
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("hiddenlink").get()));
}

TEST_F(IsDisplayedTest, ZeroHeightOrWidthIsNotDisplayed) {
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("zeroheight").get()));
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("zerowidth").get()));
}

TEST_F(IsDisplayedTest, ElementWithNestedBlockLevelElementIsDisplayed) {
  EXPECT_TRUE(algorithms::IsDisplayed(
      document_->GetElementById("containsNestedBlock").get()));
}

TEST_F(IsDisplayedTest, ZeroOpacityIsNotDisplayed) {
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("transparent").get()));
}

TEST_F(IsDisplayedTest, ZeroSizeDivHasDescendentWithSize) {
  EXPECT_TRUE(
      algorithms::IsDisplayed(document_->GetElementById("zerosizeddiv").get()));
}

TEST_F(IsDisplayedTest, ElementHiddenByOverflow) {
  // Div with zero size width and height and overflow: hidden.
  EXPECT_FALSE(
      algorithms::IsDisplayed(document_->GetElementById("bug5022").get()));
}

}  // namespace webdriver
}  // namespace cobalt
