/*
 * 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/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "cobalt/base/event_dispatcher.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"

namespace cobalt {
namespace layout_tests {

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

// 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_(system_window::CreateSystemWindow(
            &event_dispatcher_, math::Size(kViewportWidth, kViewportHeight))),
        renderer_module_(system_window_.get(),
                         renderer::RendererModule::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_callback = 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_;
  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;

  const math::Size kDefaultViewportSize(1920, 1080);
  math::Size viewport_size = test_info_.viewport_size
                                 ? *test_info_.viewport_size
                                 : kDefaultViewportSize;

  // 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());

  // 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
