// Copyright 2015 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 "base/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "cobalt/base/event_dispatcher.h"
#include "cobalt/cssom/viewport_size.h"
#include "cobalt/dom/benchmark_stat_names.h"
#include "cobalt/layout/benchmark_stat_names.h"
#include "cobalt/layout_tests/layout_snapshot.h"
#include "cobalt/layout_tests/test_parser.h"
#include "cobalt/math/size.h"
#include "cobalt/renderer/pipeline.h"
#include "cobalt/renderer/renderer_module.h"
#include "cobalt/renderer/submission.h"
#include "cobalt/system_window/system_window.h"
#include "cobalt/trace_event/benchmark.h"
#include "googleurl/src/gurl.h"

using cobalt::cssom::ViewportSize;

namespace cobalt {
namespace layout_tests {

namespace {
const int kViewportWidth = 1920;
const int kViewportHeight = 1080;

const ViewportSize kViewSize(kViewportWidth, kViewportHeight);

// The RendererBenchmarkRunner sets up an environment where we can control
// the number of benchmark samples we acquire from the renderer by counting
// each time the renderer submit complete callback is made.  It also manages
// the skipping of the first frame to avoid the first frame outlier.
class RendererBenchmarkRunner {
 public:
  RendererBenchmarkRunner()
      : done_gathering_samples_(true, false),
        system_window_(new system_window::SystemWindow(
            &event_dispatcher_, kViewSize.width_height())) {
    // Since we'd like to measure the renderer, we force it to rasterize each
    // frame despite the fact that the render tree may not be changing.
    renderer::RendererModule::Options renderer_options;
    renderer_options.submit_even_if_render_tree_is_unchanged = true;
    renderer_module_.emplace(system_window_.get(), renderer_options);
  }

  // Return the resource provider from the internal renderer so that it can
  // be used during layout.
  render_tree::ResourceProvider* GetResourceProvider() {
    return renderer_module_->pipeline()->GetResourceProvider();
  }

  // Run the renderer benchmarks and perform the measurements.
  void RunBenchmarks(const browser::WebModule::LayoutResults& layout_results,
                     int samples_to_gather) {
    // Initialize our per-RunBenchmarks() state.
    samples_to_gather_ = samples_to_gather;
    done_gathering_samples_.Reset();

    renderer::Submission submission_with_callback(layout_results.render_tree,
                                                  layout_results.layout_time);
    submission_with_callback.on_rasterized_callbacks.emplace_back(base::Bind(
        &RendererBenchmarkRunner::OnSubmitComplete, base::Unretained(this)));

    renderer_module_->pipeline()->Submit(submission_with_callback);

    done_gathering_samples_.Wait();

    renderer_module_->pipeline()->Clear();
  }

 private:
  // Called whenever the renderer completes a frame submission.  This allows us
  // to count how many frames have been submitted so we know when to stop (via
  // the signaling of the done_gathering_samples_ event).
  void OnSubmitComplete() {
    --samples_to_gather_;

    // We wait for samples_to_gather + 1 submits to complete because we actually
    // want samples_to_gather, but we skipped the first submit.
    if (samples_to_gather_ <= 0) {
      done_gathering_samples_.Signal();
    }
  }

  int samples_to_gather_;
  base::WaitableEvent done_gathering_samples_;
  base::EventDispatcher event_dispatcher_;

  scoped_ptr<system_window::SystemWindow> system_window_;
  base::optional<renderer::RendererModule> renderer_module_;
};

}  // namespace

class LayoutBenchmark : public trace_event::Benchmark {
 public:
  explicit LayoutBenchmark(const TestInfo& test_info);
  ~LayoutBenchmark() override {}

  void Experiment() override;
  void AnalyzeTraceEvent(
      const scoped_refptr<trace_event::EventParser::ScopedEvent>& event)
      override;
  std::vector<trace_event::Benchmark::Result> CompileResults() override;

 private:
  typedef base::hash_map<std::string, double> IntermediateResultsMap;
  typedef base::hash_map<std::string, std::vector<double> >
      FinalResultsSampleMap;

  void OnIterationComplete();
  static std::string FilePathToBenchmarkName(const FilePath& filepath);

  TestInfo test_info_;

  // During each iteration, we accumulate intermediate results by *adding*
  // task times together.  Only when the iteration is complete do we consider
  // our result a sample.
  IntermediateResultsMap intermediate_results_;

  // A list of accumulated intermediate results.  The vectors in this map are
  // pushed to at the end of each iteration.
  FinalResultsSampleMap layout_samples_;
  FinalResultsSampleMap renderer_samples_;

  // Is this our first iteration?
  bool first_iteration_;

  // We setup the renderer benchmark runner first so that we can gain access
  // to the resource provider and so that we can also benchmark the rendering
  // of the layed out web pages.
  RendererBenchmarkRunner renderer_benchmark_runner_;
};

LayoutBenchmark::LayoutBenchmark(const TestInfo& test_info)
    : test_info_(test_info), first_iteration_(true) {
  // Setup the name's benchmark based on the test entry file path.
  set_name(FilePathToBenchmarkName(test_info_.base_file_path));
  set_num_iterations(10, base::Bind(&LayoutBenchmark::OnIterationComplete,
                                    base::Unretained(this)));

  // Define the set of event names that we would like to watch for by
  // initializing their map entries to the default constructed values (e.g.
  // std::vector<double>()).
  layout_samples_[layout::kBenchmarkStatLayout];
  layout_samples_[dom::kBenchmarkStatUpdateSelectorTree];
  layout_samples_[dom::kBenchmarkStatUpdateComputedStyles];
  layout_samples_[layout::kBenchmarkStatBoxGeneration];
  layout_samples_[layout::kBenchmarkStatUpdateCrossReferences];
  layout_samples_[layout::kBenchmarkStatUpdateUsedSizes];
  layout_samples_[layout::kBenchmarkStatRenderAndAnimate];
  renderer_samples_["AnimateNode::Apply()"];
  renderer_samples_["VisitRenderTree"];
  renderer_samples_["Skia Flush"];
}

std::string LayoutBenchmark::FilePathToBenchmarkName(const FilePath& filepath) {
  std::vector<FilePath::StringType> components;
  filepath.GetComponents(&components);

  // Don't include the "benchmarks" directory as part of the benchmark name.
  components.erase(components.begin());

  return JoinString(components, '/');
}

void LayoutBenchmark::Experiment() {
  MessageLoop message_loop(MessageLoop::TYPE_DEFAULT);

  // We prepare a layout_results variable where we place the results from each
  // layout.  We will then use the final layout_results as input to the renderer
  // benchmark.
  base::optional<browser::WebModule::LayoutResults> layout_results;

  ViewportSize viewport_size =
      test_info_.viewport_size ? *test_info_.viewport_size : kViewSize;

  // Set up a WebModule, load the URL and trigger layout to get layout benchmark
  // results.
  layout_results =
      SnapshotURL(test_info_.url, viewport_size,
                  renderer_benchmark_runner_.GetResourceProvider(),
                  dom::ScreenshotManager::ProvideScreenshotFunctionCallback());

  // Finally run the renderer benchmarks to acquire performance data on
  // rendering.
  renderer_benchmark_runner_.RunBenchmarks(*layout_results, 60);
}

namespace {

// Return true if the event has an ancestor with the specified named event.
bool HasAncestorEvent(
    const scoped_refptr<trace_event::EventParser::ScopedEvent>& event,
    const std::string& ancestor_event_string) {
  scoped_refptr<trace_event::EventParser::ScopedEvent> ancestor_event =
      event->parent();
  while (ancestor_event) {
    if (ancestor_event->name() == ancestor_event_string) {
      break;
    }
    ancestor_event = ancestor_event->parent();
  }

  return ancestor_event.get() != NULL;
}

}  // namespace

void LayoutBenchmark::AnalyzeTraceEvent(
    const scoped_refptr<trace_event::EventParser::ScopedEvent>& event) {
  // Check if this is a layout sample.
  if (event->name() == layout::kBenchmarkStatNonMeasuredLayout) {
    // If this is a layout that should not be measured, use that as a signal
    // that we are measuring partial layout, and clear out all measured data
    // so far and start fresh for the eventual measured layout.
    intermediate_results_.clear();
    return;
  }

  FinalResultsSampleMap::iterator found_layout =
      layout_samples_.find(event->name());
  if (found_layout != layout_samples_.end() &&
      !HasAncestorEvent(event, layout::kBenchmarkStatNonMeasuredLayout)) {
    if (!ContainsKey(intermediate_results_, found_layout->first)) {
      intermediate_results_[found_layout->first] = 0;
    }

    double event_duration = event->in_scope_duration()->InSecondsF();
    intermediate_results_[found_layout->first] += event_duration;

    if (event->name() != layout::kBenchmarkStatLayout &&
        !HasAncestorEvent(event, layout::kBenchmarkStatLayout)) {
      // If the event (which we have specifically requested to include in
      // the benchmark results) does not fall under the scope of the official
      // layout event, artificially increase the tracked layout time to include
      // it.  This way events can occur at any time, and the scoped layout
      // event still gives us a way to measure unaccounted for time that we
      // know is devoted to layout.
      intermediate_results_[layout::kBenchmarkStatLayout] += event_duration;
    }
  }

  FinalResultsSampleMap::iterator found_renderer =
      renderer_samples_.find(event->name());
  if (found_renderer != renderer_samples_.end()) {
    found_renderer->second.push_back(event->in_scope_duration()->InSecondsF());
  }
}

void LayoutBenchmark::OnIterationComplete() {
  // Skip recording the results of the first iteration, since a few things
  // may have been lazily initialized and we'd like to avoid recording that.
  if (first_iteration_) {
    for (FinalResultsSampleMap::iterator iter = renderer_samples_.begin();
         iter != renderer_samples_.end(); ++iter) {
      iter->second.clear();
    }
  } else {
    // Save our finalized intermediate results into our finalized results, and
    // then clear out our intermediate results for the next iteration.
    for (FinalResultsSampleMap::iterator iter = layout_samples_.begin();
         iter != layout_samples_.end(); ++iter) {
      if (ContainsKey(intermediate_results_, iter->first)) {
        iter->second.push_back(intermediate_results_[iter->first]);
      }
    }
  }

  first_iteration_ = false;
  intermediate_results_.clear();
}

std::vector<trace_event::Benchmark::Result> LayoutBenchmark::CompileResults() {
  std::vector<trace_event::Benchmark::Result> results;
  for (FinalResultsSampleMap::iterator iter = layout_samples_.begin();
       iter != layout_samples_.end(); ++iter) {
    results.push_back(trace_event::Benchmark::Result(
        iter->first + " in-scope duration in seconds", iter->second));
  }
  for (FinalResultsSampleMap::iterator iter = renderer_samples_.begin();
       iter != renderer_samples_.end(); ++iter) {
    results.push_back(trace_event::Benchmark::Result(
        iter->first + " in-scope duration in seconds", iter->second));
  }
  return results;
}

class LayoutBenchmarkCreator : public trace_event::BenchmarkCreator {
 public:
  std::vector<CreateBenchmarkFunction> GetBenchmarkCreators() override {
    std::vector<CreateBenchmarkFunction> benchmarks;

    std::vector<TestInfo> benchmark_infos = EnumerateLayoutTests("benchmarks");
    for (std::vector<TestInfo>::const_iterator iter = benchmark_infos.begin();
         iter != benchmark_infos.end(); ++iter) {
      benchmarks.push_back(
          base::Bind(&LayoutBenchmarkCreator::CreateLayoutBenchmark, *iter));
    }

    return benchmarks;
  }

 private:
  static scoped_ptr<trace_event::Benchmark> CreateLayoutBenchmark(
      const TestInfo& test_info) {
    return scoped_ptr<trace_event::Benchmark>(new LayoutBenchmark(test_info));
  }
};
LayoutBenchmarkCreator g_benchmark_creator;

}  // namespace layout_tests
}  // namespace cobalt
