// Copyright 2016 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 "cobalt/dom/dom_stat_tracker.h"

#include "base/strings/stringprintf.h"

namespace cobalt {
namespace dom {

DomStatTracker::DomStatTracker(const std::string& name)
    : count_html_element_(
          base::StringPrintf("Count.%s.DOM.HtmlElement", name.c_str()), 0,
          "Total number of HTML elements."),
      count_html_element_document_(
          base::StringPrintf("Count.%s.DOM.HtmlElement.Document", name.c_str()),
          0, "Number of HTML elements in the document."),
      count_html_element_created_(0),
      count_html_element_destroyed_(0),
      count_html_element_document_added_(0),
      count_html_element_document_removed_(0),
      script_element_execute_count_(
          base::StringPrintf("Count.%s.DOM.HtmlScriptElement.Execute",
                             name.c_str()),
          0, "Count of HTML script element execute calls."),
      script_element_execute_total_size_(
          base::StringPrintf("Memory.%s.DOM.HtmlScriptElement.Execute",
                             name.c_str()),
          0, "Total size in bytes of HTML script elements executed."),
      script_element_execute_time_(
          base::StringPrintf("Time.%s.DOM.HtmlScriptElement.Execute",
                             name.c_str()),
          0, "Time of the last HTML script element execute."),
      is_tracking_event_(false),
      event_initial_count_html_element_(0),
      event_initial_count_html_element_document_(0),
      event_count_html_element_created_(0),
      event_count_html_element_destroyed_(0),
      event_count_html_element_document_added_(0),
      event_count_html_element_document_removed_(0),
      event_count_update_matching_rules_(0),
      event_count_update_computed_style_(0),
      event_count_generate_html_element_computed_style_(0),
      event_count_generate_pseudo_element_computed_style_(0),
      event_video_start_delay_stop_watch_(kStopWatchTypeEventVideoStartDelay,
                                          base::StopWatch::kAutoStartOff, this),
      event_video_start_delay_(
          base::StringPrintf("Event.Duration.%s.DOM.VideoStartDelay",
                             name.c_str()),
          base::TimeDelta(), "Total delay between event and video starting.") {
  stop_watch_durations_.resize(kNumStopWatchTypes, base::TimeDelta());
}

DomStatTracker::~DomStatTracker() {
  FlushPeriodicTracking();

  // Verify that all of the elements were removed from the document and
  // destroyed.
  DCHECK_EQ(count_html_element_, 0);
  DCHECK_EQ(count_html_element_document_, 0);

  event_video_start_delay_stop_watch_.Stop();
}

void DomStatTracker::OnHtmlElementCreated() {
  ++count_html_element_created_;
  if (is_tracking_event_) {
    ++event_count_html_element_created_;
  }
}

void DomStatTracker::OnHtmlElementDestroyed() {
  ++count_html_element_destroyed_;
  if (is_tracking_event_) {
    ++event_count_html_element_destroyed_;
  }
}

void DomStatTracker::OnHtmlElementInsertedIntoDocument() {
  ++count_html_element_document_added_;
  if (is_tracking_event_) {
    ++event_count_html_element_document_added_;
  }
}

void DomStatTracker::OnHtmlElementRemovedFromDocument() {
  ++count_html_element_document_removed_;
  if (is_tracking_event_) {
    ++event_count_html_element_document_removed_;
  }
}

void DomStatTracker::OnUpdateMatchingRules() {
  if (is_tracking_event_) {
    ++event_count_update_matching_rules_;
  }
}

void DomStatTracker::OnUpdateComputedStyle() {
  if (is_tracking_event_) {
    ++event_count_update_computed_style_;
  }
}

void DomStatTracker::OnGenerateHtmlElementComputedStyle() {
  if (is_tracking_event_) {
    ++event_count_generate_html_element_computed_style_;
  }
}

void DomStatTracker::OnGeneratePseudoElementComputedStyle() {
  if (is_tracking_event_) {
    ++event_count_generate_pseudo_element_computed_style_;
  }
}

void DomStatTracker::OnHtmlScriptElementExecuted(size_t script_size) {
  ++script_element_execute_count_;
  script_element_execute_total_size_ += script_size;
  script_element_execute_time_ = base::TimeTicks::Now().ToInternalValue();
}

void DomStatTracker::OnHtmlVideoElementPlaying() {
  if (event_video_start_delay_stop_watch_.IsCounting()) {
    event_video_start_delay_stop_watch_.Stop();
    event_video_start_delay_ =
        stop_watch_durations_[kStopWatchTypeEventVideoStartDelay];
  }
}

void DomStatTracker::FlushPeriodicTracking() {
  // Update the CVals before clearing the periodic values.
  count_html_element_ +=
      count_html_element_created_ - count_html_element_destroyed_;
  count_html_element_document_ +=
      count_html_element_document_added_ - count_html_element_document_removed_;

  // Now clear the values.
  count_html_element_created_ = 0;
  count_html_element_destroyed_ = 0;
  count_html_element_document_added_ = 0;
  count_html_element_document_removed_ = 0;
}

void DomStatTracker::StartTrackingEvent() {
  DCHECK(!is_tracking_event_);
  is_tracking_event_ = true;

  event_initial_count_html_element_ = count_html_element_ +
                                      count_html_element_created_ -
                                      count_html_element_destroyed_;
  event_initial_count_html_element_document_ =
      count_html_element_document_ + count_html_element_document_added_ -
      count_html_element_document_removed_;

  event_count_html_element_created_ = 0;
  event_count_html_element_destroyed_ = 0;
  event_count_html_element_document_added_ = 0;
  event_count_html_element_document_removed_ = 0;
  event_count_update_matching_rules_ = 0;
  event_count_update_computed_style_ = 0;
  event_count_generate_html_element_computed_style_ = 0;
  event_count_generate_pseudo_element_computed_style_ = 0;

  // Stop the watch before re-starting it. This ensures that the count is
  // zeroed out if it was still running from the prior event (this is a common
  // case as most events do not result in a video starting).
  event_video_start_delay_stop_watch_.Stop();
  event_video_start_delay_stop_watch_.Start();
  event_video_start_delay_ = base::TimeDelta();

  // Zero out the stop watch durations so that the numbers will only include the
  // event.
  for (size_t i = 0; i < kNumStopWatchTypes; ++i) {
    stop_watch_durations_[i] = base::TimeDelta();
  }
}

void DomStatTracker::StopTrackingEvent() {
  DCHECK(is_tracking_event_);
  is_tracking_event_ = false;
}

int DomStatTracker::EventCountHtmlElement() const {
  return event_initial_count_html_element_ + event_count_html_element_created_ -
         event_count_html_element_destroyed_;
}

int DomStatTracker::EventCountHtmlElementDocument() const {
  return event_initial_count_html_element_document_ +
         event_count_html_element_document_added_ -
         event_count_html_element_document_removed_;
}

base::TimeDelta DomStatTracker::GetStopWatchTypeDuration(
    StopWatchType type) const {
  return stop_watch_durations_[type];
}

bool DomStatTracker::IsStopWatchEnabled(int id) const {
  return is_tracking_event_ || id == kStopWatchTypeEventVideoStartDelay;
}

void DomStatTracker::OnStopWatchStopped(int id, base::TimeDelta time_elapsed) {
  stop_watch_durations_[static_cast<size_t>(id)] += time_elapsed;
}

}  // namespace dom
}  // namespace cobalt
