// Copyright 2021 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/performance_observer.h"

#include <unordered_set>

#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/performance.h"
#include "cobalt/dom/performance_entry.h"
#include "cobalt/dom/window.h"

namespace cobalt {
namespace dom {

namespace {
// Implement the CallbackInternal interface for a JavaScript callback.
class ScriptCallback : public PerformanceObserver::CallbackInternal {
 public:
  ScriptCallback(
      const PerformanceObserver::PerformanceObserverCallbackArg& callback,
      PerformanceObserver* observer)
      : callback_(observer, callback) {}
  bool RunCallback(
      const scoped_refptr<PerformanceObserverEntryList>& entries,
      const scoped_refptr<PerformanceObserver>& observer) override {
    // ScriptCallback's lifetime is bined with JS PerformanceObserver object. We
    // should not run callback, When JS object has been destroyed.
    if (callback_.referenced_value().IsNull()) return false;
    script::CallbackResult<void> result =
        callback_.value().Run(entries, observer);
    return !result.exception;
  }

 private:
  PerformanceObserver::PerformanceObserverCallbackArg::Reference callback_;
};

// Implement the CallbackInternal interface for a native callback.
class NativeCallback : public PerformanceObserver::CallbackInternal {
 public:
  explicit NativeCallback(
      const PerformanceObserver::NativePerformanceObserverCallback& callback)
      : callback_(callback) {}
  bool RunCallback(
      const scoped_refptr<PerformanceObserverEntryList>& entries,
      const scoped_refptr<PerformanceObserver>& observer) override {
    callback_.Run(entries, observer);
    return true;
  }

 private:
  PerformanceObserver::NativePerformanceObserverCallback callback_;
};

}  // namespace

PerformanceObserver::PerformanceObserver(
    const NativePerformanceObserverCallback& native_callback,
    const scoped_refptr<Performance>& performance)
    : performance_(base::AsWeakPtr(performance.get())),
      observer_type_(PerformanceObserverType::kUndefined),
      is_registered_(false) {
  callback_.reset(new NativeCallback(native_callback));
}

PerformanceObserver::PerformanceObserver(
    script::EnvironmentSettings* env_settings,
    const PerformanceObserverCallbackArg& callback)
    : performance_(
          base::AsWeakPtr(base::polymorphic_downcast<DOMSettings*>(env_settings)
                              ->window()
                              ->performance()
                              .get())),
      observer_type_(PerformanceObserverType::kUndefined),
      is_registered_(false) {
  callback_.reset(new ScriptCallback(callback, this));
}

PerformanceObserver::~PerformanceObserver() {}

void PerformanceObserver::Observe(const PerformanceObserverInit& options,
                                  script::ExceptionState* exception_state) {
  // The algorithm for registering the observer.
  //   https://www.w3.org/TR/2019/WD-performance-timeline-2-20191024/#observe-method
  // 1.  Let observer be the context object.
  // 2.  Let relevantGlobal be observer's relevant global object.
  if (!performance_) {
    return;
  }
  // 3.  If options's entryTypes and type members are both omitted, then throw
  // a SyntaxError.
  bool has_entry_types = options.has_entry_types();
  bool has_type = options.has_type();
  if (!has_entry_types && !has_type) {
    DOMException::Raise(DOMException::kSyntaxErr, exception_state);
  }
  // 4.  If options's entryTypes is present and any other member is also
  // present, then throw a SyntaxError.
  bool entry_types_present = has_entry_types && !options.entry_types().empty();
  bool type_present = has_type && !options.type().empty();
  if (entry_types_present && type_present) {
    DOMException::Raise(DOMException::kSyntaxErr, exception_state);
  }
  // 5.  Update or check observer's observer type by running these steps:
  // 5.1   If observer's observer type is "undefined":
  if (observer_type_ == PerformanceObserverType::kUndefined) {
    // 5.1.1  If options's entryTypes member is present, then set observer's
    // observer type to "multiple".
    if (entry_types_present) {
      observer_type_ = PerformanceObserverType::kMultiple;
    }
    // 5.1.2  If options's type member is present, then set observer's
    // observer type to "single".
    if (type_present) {
      observer_type_ = PerformanceObserverType::kSingle;
    }
  }
  // 5.2  If observer's observer type is "single" and options's entryTypes
  // member is present, then throw an InvalidModificationError.
  if (observer_type_ == PerformanceObserverType::kSingle &&
      entry_types_present) {
    DOMException::Raise(DOMException::kInvalidModificationErr, exception_state);
  }
  // 5.3  If observer's observer type is "multiple" and options's type member
  // is present, then throw an InvalidModificationError.
  if (observer_type_ == PerformanceObserverType::kMultiple && type_present) {
    DOMException::Raise(DOMException::kInvalidModificationErr, exception_state);
  }
  // 6  If observer's observer type is "multiple", run the following steps:
  if (observer_type_ == PerformanceObserverType::kMultiple) {
    // 6.1  Let entry types be options's entryTypes sequence.
    script::Sequence<std::string> entry_types;
    // 6.2  Remove all types from entry types that are not contained in
    // relevantGlobal's frozen array of supported entry types. The user agent
    // SHOULD notify developers if entry types is modified. For example, a
    // console warning listing removed types might be appropriate.
    for (const auto& entry_type_string : options.entry_types()) {
      PerformanceEntryType entry_type =
          PerformanceEntry::ToEntryTypeEnum(entry_type_string);
      if (entry_type != PerformanceEntry::kInvalid) {
        entry_types.push_back(entry_type_string);
      } else {
        DLOG(WARNING) << "The entry type " + entry_type_string +
                             " does not exist or isn't supported.";
      }
    }
    // 6.3  If the resulting entry types sequence is an empty sequence,
    // abort these steps. The user agent SHOULD notify developers when the
    // steps are aborted to notify that registration has been aborted.
    // For example, a console warning might be appropriate.
    if (entry_types.empty()) {
      DLOG(WARNING) << "An observe() call must include either entryTypes.";
      return;
    }
    // 6.4  If the list of registered performance observer objects of
    // relevantGlobal contains a registered performance observer whose
    // observer is the context object, replace its options list with a list
    // containing options as its only item.
    if (is_registered_) {
      performance_->ReplaceRegisteredPerformanceObserverOptionsList(
          base::WrapRefCounted(this), options);
      // 6.5  Otherwise, create and append a registered performance observer
      // object to the list of registered performance observer objects of
      // relevantGlobal, with observer set to the context object and options
      // list set to a list containing options as its only item.
    } else {
      performance_->RegisterPerformanceObserver(base::WrapRefCounted(this),
                                                options);
      is_registered_ = true;
    }
    // 7.  Otherwise, run the following steps:
  } else {
    // 7.1  Assert that observer's observer type is "single".
    DCHECK(observer_type_ == PerformanceObserverType::kSingle);
    // 7.2  If options's type is not contained in the relevantGlobal's frozen
    // array of supported entry types, abort these steps. The user agent SHOULD
    // notify developers when this happens, for instance via a console warning.
    PerformanceEntryType options_type =
        PerformanceEntry::ToEntryTypeEnum(options.type());
    if (options_type == PerformanceEntry::kInvalid) {
      DLOG(WARNING) << "The type " + options.type() +
                           " does not exist or isn't supported.";
      return;
    }
    // 7.3  If the list of registered performance observer objects of
    // relevantGlobal contains a registered performance observer obs whose
    // observer is the context object:
    if (is_registered_) {
      // 7.3.1  If obs's options list contains a PerformanceObserverInit item
      // currentOptions whose type is equal to options's type, replace
      // currentOptions with options in obs's options list.
      // 7.3.2  Otherwise, append options to obs's options list.
      performance_->UpdateRegisteredPerformanceObserverOptionsList(
          base::WrapRefCounted(this), options);
      // 7.4  Otherwise, create and append a registered performance observer
      // object to the list of registered performance observer objects of
      // relevantGlobal, with observer set to the context object and options
      // list set to a list containing options as its only item.
    } else {
      performance_->RegisterPerformanceObserver(base::WrapRefCounted(this),
                                                options);
      is_registered_ = true;
    }
  }
}

void PerformanceObserver::Observe(script::ExceptionState* exception_state) {
  PerformanceObserverInit options;
  Observe(options, exception_state);
}

void PerformanceObserver::Disconnect() {
  // The disconnect() method must remove the context object from the list of
  // registered performance observer objects of relevant global object, and
  // also empty context object's observer buffer.
  //   https://www.w3.org/TR/2019/WD-performance-timeline-2-20191024/#disconnect-method
  if (performance_) {
    performance_->UnregisterPerformanceObserver(base::WrapRefCounted(this));
  }
  observer_buffer_.clear();
  is_registered_ = false;
}

PerformanceEntryList PerformanceObserver::TakeRecords() {
  // The takeRecords() method must return a copy of the context object's
  // observer buffer, and also empty context object's observer buffer.
  //   https://www.w3.org/TR/2019/WD-performance-timeline-2-20191024/#takerecords-method
  PerformanceEntryList performance_entries;
  performance_entries.swap(observer_buffer_);
  return performance_entries;
}

script::Sequence<std::string> PerformanceObserver::supported_entry_types() {
  // Each global object has an associated frozen array of supported entry
  // types, which is initialized to the FrozenArray created from the
  // sequence of strings among the registry that are supported for the
  // global object, in alphabetical order.
  //   https://www.w3.org/TR/2019/WD-performance-timeline-2-20191024/#supportedentrytypes-attribute
  // TODO: Implement the 'Time Entry Names Registry'.
  //   // https://w3c.github.io/timing-entrytypes-registry/#registry
  // When supportedEntryTypes's attribute getter is called, run the
  // following steps:
  // 1.  Let globalObject be the environment settings object's global object.
  script::Sequence<std::string> supported_entry_type_list;
  for (size_t i = 0; i < arraysize(PerformanceEntry::kEntryTypeString); ++i) {
    const char* entry_type = PerformanceEntry::kEntryTypeString[i];
    if (!base::LowerCaseEqualsASCII("invalid", entry_type)) {
      std::string entry_type_string(entry_type);
      supported_entry_type_list.push_back(entry_type_string);
    }
  }

  // 2.  Return globalObject's frozen array of supported entry types.
  return supported_entry_type_list;
}

void PerformanceObserver::EnqueuePerformanceEntry(
    const scoped_refptr<PerformanceEntry>& entry) {
  observer_buffer_.push_back(entry);
}

void PerformanceObserver::TraceMembers(script::Tracer* tracer) {
  tracer->TraceItems(observer_buffer_);
}

}  // namespace dom
}  // namespace cobalt
