// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/public/python/src/python_system_helper.h"

#include "Python.h"

#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/cpp/environment/logging.h"
#include "mojo/public/cpp/system/macros.h"
#include "mojo/public/cpp/utility/run_loop.h"

namespace {

class ScopedGIL {
 public:
  ScopedGIL() { state_ = PyGILState_Ensure(); }

  ~ScopedGIL() { PyGILState_Release(state_); }

 private:
  PyGILState_STATE state_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedGIL);
};

enum ScopedPyRefAcquire {
  kAcquire,
};

class ScopedPyRef {
 public:
  ScopedPyRef(PyObject* object) : object_(object) {}
  ScopedPyRef(PyObject* object, ScopedPyRefAcquire) : object_(object) {
    Py_XINCREF(object_);
  }

  ~ScopedPyRef() {
    if (object_) {
      ScopedGIL acquire_gil;
      Py_DECREF(object_);
    }
  }

  operator PyObject*() const { return object_; }

 private:
  PyObject* object_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedPyRef);
};

class PythonClosure : public mojo::Closure::Runnable {
 public:
  PythonClosure(PyObject* callable) : callable_(callable, kAcquire) {
    MOJO_DCHECK(callable);
  }

  void Run() const override {
    ScopedGIL acquire_gil;
    ScopedPyRef empty_tuple(PyTuple_New(0));
    if (!empty_tuple) {
      mojo::RunLoop::current()->Quit();
      return;
    }

    ScopedPyRef result(PyObject_CallObject(callable_, empty_tuple));
    if (!result) {
      mojo::RunLoop::current()->Quit();
      return;
    }
  }

 private:
  ScopedPyRef callable_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(PythonClosure);
};

void AsyncCallbackForwarder(void* closure, MojoResult result) {
  mojo::Callback<void(MojoResult)>* callback =
      static_cast<mojo::Callback<void(MojoResult)>*>(closure);
  // callback will be deleted when it is run.
  callback->Run(result);
}

}  // namespace

namespace mojo {
namespace python {

class PythonAsyncWaiter::AsyncWaiterRunnable
    : public mojo::Callback<void(MojoResult)>::Runnable {
 public:
  AsyncWaiterRunnable(PyObject* callable, CallbackMap* callbacks)
      : wait_id_(0), callable_(callable, kAcquire), callbacks_(callbacks) {
    MOJO_DCHECK(callable);
    MOJO_DCHECK(callbacks_);
  }

  void set_wait_id(int wait_id) { wait_id_ = wait_id; }

  void Run(MojoResult mojo_result) const override {
    MOJO_DCHECK(wait_id_);

    // Remove to reference to this object from PythonAsyncWaiter and ensure this
    // object will be destroyed when this method exits.
    MOJO_DCHECK(callbacks_->find(wait_id_) != callbacks_->end());
    internal::SharedPtr<mojo::Callback<void(MojoResult)>> self =
        (*callbacks_)[wait_id_];
    callbacks_->erase(wait_id_);

    ScopedGIL acquire_gil;
    ScopedPyRef args_tuple(Py_BuildValue("(i)", mojo_result));
    if (!args_tuple) {
      mojo::RunLoop::current()->Quit();
      return;
    }

    ScopedPyRef result(PyObject_CallObject(callable_, args_tuple));
    if (!result) {
      mojo::RunLoop::current()->Quit();
      return;
    }
  }

 private:
  MojoAsyncWaitID wait_id_;
  ScopedPyRef callable_;
  CallbackMap* callbacks_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiterRunnable);
};

Closure BuildClosure(PyObject* callable) {
  if (!PyCallable_Check(callable))
    return Closure();

  return Closure(
      static_cast<mojo::Closure::Runnable*>(new PythonClosure(callable)));
}

PythonAsyncWaiter::PythonAsyncWaiter() {
  async_waiter_ = Environment::GetDefaultAsyncWaiter();
}

PythonAsyncWaiter::~PythonAsyncWaiter() {
  for (CallbackMap::const_iterator it = callbacks_.begin();
       it != callbacks_.end();
       ++it) {
    async_waiter_->CancelWait(it->first);
  }
}

MojoAsyncWaitID PythonAsyncWaiter::AsyncWait(MojoHandle handle,
                                             MojoHandleSignals signals,
                                             MojoDeadline deadline,
                                             PyObject* callable) {
  AsyncWaiterRunnable* runner = new AsyncWaiterRunnable(callable, &callbacks_);
  internal::SharedPtr<mojo::Callback<void(MojoResult)>> callback(
      new mojo::Callback<void(MojoResult)>(
          static_cast<mojo::Callback<void(MojoResult)>::Runnable*>(runner)));
  MojoAsyncWaitID wait_id = async_waiter_->AsyncWait(
      handle, signals, deadline, &AsyncCallbackForwarder, callback.get());
  callbacks_[wait_id] = callback;
  runner->set_wait_id(wait_id);
  return wait_id;
}

void PythonAsyncWaiter::CancelWait(MojoAsyncWaitID wait_id) {
  if (callbacks_.find(wait_id) != callbacks_.end()) {
    async_waiter_->CancelWait(wait_id);
    callbacks_.erase(wait_id);
  }
}

}  // namespace python
}  // namespace mojo
