// Copyright 2015 Google Inc. 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.

#ifndef COBALT_WEBDRIVER_UTIL_CALL_ON_MESSAGE_LOOP_H_
#define COBALT_WEBDRIVER_UTIL_CALL_ON_MESSAGE_LOOP_H_

#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/synchronization/waitable_event.h"

namespace cobalt {
namespace webdriver {
namespace util {
namespace internal {
template <class ReturnValue>
class CallOnMessageLoopHelper {
 public:
  typedef base::Callback<ReturnValue(void)> CallbackType;
  CallOnMessageLoopHelper(
      const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
      const CallbackType& callback)
      : completed_event_(true, false), success_(false) {
    DCHECK_NE(base::MessageLoopProxy::current(), message_loop_proxy);
    scoped_ptr<DeletionSignaler> dt(new DeletionSignaler(&completed_event_));
    // Note that while MessageLoopProxy::PostTask returns false
    // after the message loop has gone away, it still can return true
    // even if tasks are posted during shutdown and will never be run,
    // so we ignore this return value.
    message_loop_proxy->PostTask(
        FROM_HERE,
        base::Bind(&CallOnMessageLoopHelper::Call, base::Unretained(this),
                   callback, base::Passed(&dt)));
  }

  // Waits for result, filling |out| with the return value if successful.
  // Returns true on success or false if the message loop went away
  // before the task was executed.
  bool WaitForResult(ReturnValue* out) {
    completed_event_.Wait();
    if (success_) {
      *out = result_;
    }
    return success_;
  }

  ~CallOnMessageLoopHelper() {
    // We must ensure that we've waited for completion otherwise
    // DeletionSignaler will have a use-after-free.
    completed_event_.Wait();
  }

 private:
  // DeletionSignaler signals an event when the destructor is called.
  // This allows us to use the base::Passed mechanism to signal our
  // completed_event_ both when Call() has been invoked and when
  // the message loop has been deleted.
  class DeletionSignaler {
   public:
    base::WaitableEvent* to_signal_;

    explicit DeletionSignaler(base::WaitableEvent* to_signal)
        : to_signal_(to_signal) {}

    ~DeletionSignaler() { to_signal_->Signal(); }

   private:
    DISALLOW_COPY_AND_ASSIGN(DeletionSignaler);
  };

  void Call(const CallbackType& callback,
            scoped_ptr<DeletionSignaler> dt ALLOW_UNUSED) {
    result_ = callback.Run();
    success_ = true;
  }

  base::WaitableEvent completed_event_;
  ReturnValue result_;
  bool success_;
};

// Used with CallWeakOnMessageLoop.
template <typename T, typename ReturnValue>
base::optional<ReturnValue> RunWeak(const base::Callback<T*()>& get_weak,
                                    const base::Callback<ReturnValue(T*)>& cb) {
  T* weak_object = get_weak.Run();
  if (weak_object) {
    return cb.Run(weak_object);
  } else {
    return base::nullopt;
  }
}
}  // namespace internal

// Call the base::Callback on the specified message loop and wait for it to
// complete. Returns true if successful, or false if the underlying
// PostTask failed. This can happen if a WebModule shuts down due to a page
// navigation.
//
// On success, |out| is set to the result.
template <class ReturnValue>
bool TryCallOnMessageLoop(
    const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
    const base::Callback<ReturnValue(void)>& callback, ReturnValue* out) {
  internal::CallOnMessageLoopHelper<ReturnValue> call_helper(message_loop_proxy,
                                                             callback);
  return call_helper.WaitForResult(out);
}

// Tries to call |callback| on messageloop |message_loop_proxy|,
// but returns a CommandResult of |window_disappeared_code| if the
// message loop has shut down. This can happen if a WebModule shuts
// down due to a page navigation.
template <typename ReturnValue>
util::CommandResult<ReturnValue> CallOnMessageLoop(
    const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
    const base::Callback<util::CommandResult<ReturnValue>(void)>& callback,
    protocol::Response::StatusCode window_disappeared_code) {
  util::CommandResult<ReturnValue> result;
  bool success = TryCallOnMessageLoop(message_loop_proxy, callback, &result);

  if (!success) {
    result =
        util::CommandResult<ReturnValue>(window_disappeared_code, "", true);
  }
  return result;
}

// Supports a common pattern in the various XXXDriver classes.
// On the provided message loop, calls RunWeak which will run the callback |cb|
// if |get_weak| returns a non-NULL pointer. RunWeak will return the result of
// the callback, or base::nullopt if |get_weak| returned NULL and the callback
// wasn't run.
// If the return value from RunWeak is valid, return a CommandResult that wraps
// the value. Otherwise return |no_such_object_code| to indicate the correct
// error.
template <typename T, typename ReturnValue>
util::CommandResult<ReturnValue> CallWeakOnMessageLoopAndReturnResult(
    const scoped_refptr<base::MessageLoopProxy>& message_loop,
    const base::Callback<T*()>& get_weak,
    const base::Callback<ReturnValue(T*)>& cb,
    protocol::Response::StatusCode no_such_object_code) {
  typedef util::CommandResult<ReturnValue> CommandResult;
  typedef base::optional<ReturnValue> InternalResult;
  InternalResult result;
  bool success = util::TryCallOnMessageLoop(
      message_loop,
      base::Bind(&internal::RunWeak<T, ReturnValue>, get_weak, cb), &result);
  if (success && result) {
    return CommandResult(result.value());
  } else {
    return CommandResult(no_such_object_code);
  }
}

}  // namespace util
}  // namespace webdriver
}  // namespace cobalt

#endif  // COBALT_WEBDRIVER_UTIL_CALL_ON_MESSAGE_LOOP_H_
