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