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

// Abstract base class for a PerformancObserverCallback.
class PerformanceObserver::CallbackInternal {
 public:
  virtual bool RunCallback(const scoped_refptr<PerformanceObserverEntryList>& entries,
                           const scoped_refptr<PerformanceObserver>& observer) = 0;
  virtual ~CallbackInternal() {}
};

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 {
    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(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(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(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(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(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
