// Copyright 2017 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/mutation_observer.h"

#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/mutation_observer_task_manager.h"
#include "cobalt/dom/node.h"
#include "cobalt/script/exception_message.h"

namespace cobalt {
namespace dom {
namespace {
// script::ExceptionState that will DCHECK on exception.
class NativeExceptionState : public script::ExceptionState {
 public:
  void SetException(const scoped_refptr<script::ScriptException>&) override {
    NOTREACHED();
  }

  void SetSimpleExceptionVA(script::SimpleExceptionType, const char*,
                            va_list) override {
    NOTREACHED();
  }
};
}  // namespace
// Abstract base class for a MutationCallback.
class MutationObserver::CallbackInternal {
 public:
  virtual bool RunCallback(const MutationRecordSequence& mutations,
                           const scoped_refptr<MutationObserver>& observer) = 0;
  virtual ~CallbackInternal() {}
};

namespace {
// Implement the CallbackInternal interface for a JavaScript callback.
class ScriptCallback : public MutationObserver::CallbackInternal {
 public:
  ScriptCallback(const MutationObserver::MutationCallbackArg& callback,
                 MutationObserver* owner)
      : callback_(owner, callback) {}
  bool RunCallback(const MutationObserver::MutationRecordSequence& mutations,
                   const scoped_refptr<MutationObserver>& observer) override {
    script::CallbackResult<void> result =
        callback_.value().Run(mutations, observer);
    return !result.exception;
  }

 private:
  MutationObserver::MutationCallbackArg::Reference callback_;
};

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

 private:
  MutationObserver::NativeMutationCallback callback_;
};

}  // namespace

MutationObserver::MutationObserver(
    const NativeMutationCallback& native_callback,
    MutationObserverTaskManager* task_manager)
    : task_manager_(task_manager) {
  callback_.reset(new NativeCallback(native_callback));
  task_manager_->OnMutationObserverCreated(this);
}

MutationObserver::MutationObserver(script::EnvironmentSettings* settings,
                                   const MutationCallbackArg& callback)
    : task_manager_(base::polymorphic_downcast<DOMSettings*>(settings)
                        ->mutation_observer_task_manager()) {
  callback_.reset(new ScriptCallback(callback, this));
  task_manager_->OnMutationObserverCreated(this);
}

MutationObserver::~MutationObserver() {
  task_manager_->OnMutationObserverDestroyed(this);
}

void MutationObserver::Observe(const scoped_refptr<Node>& target,
                               const MutationObserverInit& options) {
  NativeExceptionState exception_state;
  ObserveInternal(target, options, &exception_state);
}

void MutationObserver::Disconnect() {
  // The disconnect() method must, for each node in the context object's
  // list of nodes, remove any registered observer on node for which the context
  // object is the observer, and also empty context object's record queue.
  for (WeakNodeVector::iterator it = observed_nodes_.begin();
       it != observed_nodes_.end(); ++it) {
    dom::Node* node = it->get();
    if (node != NULL) {
      node->UnregisterMutationObserver(base::WrapRefCounted(this));
    }
  }
  observed_nodes_.clear();
  record_queue_.clear();
}

MutationObserver::MutationRecordSequence MutationObserver::TakeRecords() {
  // The takeRecords() method must return a copy of the record queue and then
  // empty the record queue.
  MutationRecordSequence record_queue;
  record_queue.swap(record_queue_);
  return record_queue;
}

void MutationObserver::QueueMutationRecord(
    const scoped_refptr<MutationRecord>& record) {
  TRACE_EVENT0("cobalt::dom", "MutationObserver::QueueMutationRecord()");
  record_queue_.push_back(record);
  task_manager_->QueueMutationObserverMicrotask();
}

bool MutationObserver::Notify() {
  TRACE_EVENT0("cobalt::dom", "MutationObserver::Notify()");
  // https://www.w3.org/TR/dom/#mutationobserver
  // Step 3 of "notify mutation observers" steps:
  //     1. Let queue be a copy of mo's record queue.
  //     2. Empty mo's record queue.
  MutationRecordSequence records = TakeRecords();

  //     3. Remove all transient registered observers whose observer is mo.
  // TODO: handle transient registered observers.

  //     4. If queue is non-empty, call mo's callback with queue as first
  //        argument, and mo (itself) as second argument and callback this
  //        value. If this throws an exception, report the exception.
  if (!records.empty()) {
    return callback_->RunCallback(records, base::WrapRefCounted(this));
  }
  // If no records, return true to indicate no error occurred.
  return true;
}

void MutationObserver::TraceMembers(script::Tracer* tracer) {
  tracer->TraceItems(observed_nodes_);
  tracer->TraceItems(record_queue_);
}

void MutationObserver::TrackObservedNode(const scoped_refptr<dom::Node>& node) {
  for (WeakNodeVector::iterator it = observed_nodes_.begin();
       it != observed_nodes_.end();) {
    if (it->get() == NULL) {
      it = observed_nodes_.erase(it);
      continue;
    }
    if (*it == node) {
      return;
    }
    ++it;
  }
  observed_nodes_.push_back(base::AsWeakPtr(node.get()));
}

void MutationObserver::ObserveInternal(
    const scoped_refptr<Node>& target, const MutationObserverInit& options,
    script::ExceptionState* exception_state) {
  if (!target) {
    // |target| is not nullable, so if this is NULL that indicates a bug in the
    // bindings layer.
    NOTREACHED();
    return;
  }
  if (!target->RegisterMutationObserver(base::WrapRefCounted(this), options)) {
    // This fails if the options are invalid.
    exception_state->SetSimpleException(script::kTypeError, "Invalid options.");
    return;
  }
  TrackObservedNode(target);
}

}  // namespace dom
}  // namespace cobalt
