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