// Copyright 2017 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 <string>
#include <vector>

#include "base/base_paths.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "cobalt/accessibility/screen_reader.h"
#include "cobalt/accessibility/text_alternative.h"
#include "cobalt/accessibility/tts_engine.h"
#include "cobalt/browser/web_module.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/window.h"
#include "cobalt/test/document_loader.h"
#include "starboard/window.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;

namespace cobalt {
namespace accessibility {
namespace {
struct TestInfo {
  TestInfo(const std::string& html_file_name,
           const std::string& expected_result,
           bool screen_reader_enabled)
      : html_file_name(html_file_name),
        expected_result(expected_result),
        screen_reader_enabled(screen_reader_enabled) {}
  std::string html_file_name;
  std::string expected_result;
  bool screen_reader_enabled;
};

// Enumerate the *.html files in the accessibility_test directory and build
// a list of input .html files and expected results.
std::vector<TestInfo> EnumerateTests(bool screen_reader_enabled,
                                     const std::string& subdir) {
  std::vector<TestInfo> infos;
  FilePath root_directory;
  PathService::Get(base::DIR_TEST_DATA, &root_directory);
  root_directory = root_directory.Append("cobalt")
                       .Append("accessibility")
                       .Append("testdata")
                       .Append(subdir);
  file_util::FileEnumerator enumerator(root_directory, false,
                                       file_util::FileEnumerator::FILES);
  for (FilePath html_file = enumerator.Next(); !html_file.empty();
       html_file = enumerator.Next()) {
    if (html_file.Extension() == ".html") {
      FilePath expected_results_file = html_file.ReplaceExtension(".expected");
      std::string results;
      if (!file_util::ReadFileToString(expected_results_file, &results)) {
        DLOG(WARNING) << "Failed to read results from file: "
                      << expected_results_file.value();
        continue;
      }
      TrimWhitespaceASCII(results, TRIM_ALL, &results);
      infos.push_back(TestInfo(html_file.BaseName().value(),
                               results,
                               screen_reader_enabled));
    }
  }
  return infos;
}

class MockTTSEngine : public TTSEngine {
 public:
  MOCK_METHOD1(Speak, void(const std::string&));
  MOCK_METHOD1(SpeakNow, void(const std::string&));
};

class TextAlternativeTest : public ::testing::TestWithParam<TestInfo> {
 protected:
  test::DocumentLoader document_loader_;
};

class LiveRegionMutationTest : public ::testing::TestWithParam<TestInfo> {
 public:
  LiveRegionMutationTest() : quit_event_(true, false) {}
  void OnError(const GURL&, const std::string& error) {
    DLOG(ERROR) << error;
    Quit();
  }
  void Quit() {
    quit_event_.Signal();
    screen_reader_.reset();
  }
  void OnClose(base::TimeDelta close_time) {
    UNREFERENCED_PARAMETER(close_time);
    Quit();
  }

  scoped_refptr<script::Wrappable> CreateWindowAttribute(
      const scoped_refptr<dom::Window>& window,
      dom::MutationObserverTaskManager* mutation_observer_task_manager,
      script::GlobalEnvironment* global_environment) {
    UNREFERENCED_PARAMETER(global_environment);
    screen_reader_.reset(new accessibility::ScreenReader(
        window->document(), &tts_engine_, mutation_observer_task_manager));
    screen_reader_->set_enabled(GetParam().screen_reader_enabled);
    EXPECT_EQ(GetParam().screen_reader_enabled, screen_reader_->enabled());

    return NULL;
  }

  static void OnRenderTreeProducedStub(
      const browser::WebModule::LayoutResults&) {}

 protected:
  MockTTSEngine tts_engine_;
  base::WaitableEvent quit_event_;
  scoped_ptr<accessibility::ScreenReader> screen_reader_;
};
}  // namespace

TEST_P(TextAlternativeTest, TextAlternativeTest) {
  GURL url(
      std::string("file:///cobalt/accessibility/testdata/text_alternative/" +
                  GetParam().html_file_name));
  document_loader_.Load(url);
  ASSERT_TRUE(document_loader_.document());
  scoped_refptr<dom::Element> element =
      document_loader_.document()->GetElementById("element_to_test");
  ASSERT_TRUE(element);
  EXPECT_EQ(GetParam().expected_result, ComputeTextAlternative(element));
}

// This test broke  because LiveRegionMutationTest::CreateWindowAttribute()
// returns a NULL script::Wrappable, which the javascript engine will attempt
// to dereference.
TEST_P(LiveRegionMutationTest, DISABLED_LiveRegionMutationTest) {
  GURL url(std::string("file:///cobalt/accessibility/testdata/live_region/" +
                       GetParam().html_file_name));
  const math::Size kDefaultViewportSize(1280, 720);
  const float kDefaultVideoPixelRatio = 1.0f;
  const float kRefreshRate = 60.0f;

  network::NetworkModule network_module((network::NetworkModule::Options()));
  render_tree::ResourceProviderStub resource_provider;

  // Use test runner mode to allow the content itself to dictate when it is
  // ready for layout should be performed.  See cobalt/dom/test_runner.h.
  browser::WebModule::Options web_module_options;
  web_module_options.injected_window_attributes["test"] = base::Bind(
      &LiveRegionMutationTest::CreateWindowAttribute, base::Unretained(this));

  // Set expected result from mutation.
  std::string expected_speech = GetParam().expected_result;
  if (expected_speech.empty() || !GetParam().screen_reader_enabled) {
    EXPECT_CALL(tts_engine_, Speak(_)).Times(0);
  } else {
    EXPECT_CALL(tts_engine_, Speak(expected_speech));
  }

  // Create the webmodule and let it run.
  DLOG(INFO) << url.spec();
  browser::WebModule web_module(
      url, base::kApplicationStateStarted,
      base::Bind(&LiveRegionMutationTest::OnRenderTreeProducedStub),
      base::Bind(&LiveRegionMutationTest::OnError, base::Unretained(this)),
      base::Bind(&LiveRegionMutationTest::OnClose, base::Unretained(this)),
      base::Closure(), /* window_minimize_callback */
      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
      &network_module, kDefaultViewportSize, kDefaultVideoPixelRatio,
      &resource_provider, kRefreshRate, web_module_options);

  // Wait for the test to quit.
  quit_event_.Wait();
}

INSTANTIATE_TEST_CASE_P(
    TextAlternativeTest, TextAlternativeTest,
    ::testing::ValuesIn(EnumerateTests(true, "text_alternative")));

INSTANTIATE_TEST_CASE_P(
    LiveRegionMutationTestEnabled, LiveRegionMutationTest,
    ::testing::ValuesIn(EnumerateTests(true, "live_region")));

INSTANTIATE_TEST_CASE_P(
    LiveRegionMutationTestDisabled, LiveRegionMutationTest,
    ::testing::ValuesIn(EnumerateTests(false, "live_region")));
}  // namespace accessibility
}  // namespace cobalt
