/**
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 <queue>
#include <v8.h>

#include "logging.h"
#include "js_support.h"
#include "node_object_wrap.h"
#include "node_util.h"
#include "util.h"
#include "worker.h"

#include "worker_v8.h"


//#define WORKER_V8_V8_DEBUG
#ifdef  WORKER_V8_V8_DEBUG

#define DBG(...) ALOGD(__VA_ARGS__)

#else

#define DBG(...)

#endif

v8::Persistent<v8::FunctionTemplate> WorkerV8Template;

class WorkerV8 : public ObjectWrap {
  private:
    friend class Handler;


    struct ArgInfo {
        v8::Persistent<v8::Object> js_this;
        v8::Persistent<v8::Value> value;
    };

    pthread_mutex_t ai_free_list_mutex_;
    std::queue<ArgInfo *>  ai_free_list_;

    ArgInfo *ObtainArgInfo() {
        ArgInfo *ai;
        pthread_mutex_lock(&ai_free_list_mutex_);
        if (ai_free_list_.size() == 0) {
            ai = new ArgInfo();
        } else {
            ai = ai_free_list_.front();
            ai_free_list_.pop();
        }
        pthread_mutex_unlock(&ai_free_list_mutex_);
        return ai;
    }

    void ReleaseArgInfo(ArgInfo *ai) {
        pthread_mutex_lock(&ai_free_list_mutex_);
        ai_free_list_.push(ai);
        pthread_mutex_unlock(&ai_free_list_mutex_);
    }

    class Handler : public WorkerQueue {
      private:
        v8::Persistent<v8::Value> functionValue_;
        WorkerV8 *worker_;

      public:
        Handler(WorkerV8 *worker, v8::Handle<v8::Value> value)
            : worker_(worker) {
            functionValue_ = v8::Persistent<v8::Value>::New(value);
        }

        void Process(void *param) {
            DBG("Handler::Process: E");

            v8::Locker locker;
            v8::HandleScope handle_scope;
            v8::TryCatch try_catch;
            try_catch.SetVerbose(true);

            ArgInfo *ai = (ArgInfo*)param;
            v8::Handle<v8::Value> args(ai->value);
            v8::Function::Cast(*functionValue_)->Call(ai->js_this, 1, &args);

            ai->js_this.Dispose();
            ai->value.Dispose();

            worker_->ReleaseArgInfo(ai);

            DBG("Handler::Process: X");
        }
    };

    Handler *handler_;

  public:
    WorkerV8(v8::Handle<v8::Object> self, v8::Handle<v8::Value> functionValue) {
        DBG("WorkerV8::WorkerV8 E:");
        pthread_mutex_init(&ai_free_list_mutex_, NULL);
        handler_ = new Handler(this, functionValue);
        Wrap(self);
        DBG("WorkerV8::WorkerV8 X: this=%p handler_=%p", this, handler_);
    }

    virtual ~WorkerV8() {
        DBG("~WorkerV8::WorkerV8 E:");
        DBG("~WorkerV8::WorkerV8 X:");
    }

    static v8::Handle<v8::Value> Run(const v8::Arguments& args) {
        WorkerV8 *workerV8 = ObjectWrap::Unwrap<WorkerV8>(args.This());
        DBG("WorkerV8::Run(args) E:");
        workerV8->handler_->Run();
        DBG("WorkerV8::Run(args) X:");
        return v8::Undefined();
    }

    static v8::Handle<v8::Value> Add(const v8::Arguments& args) {
        DBG("WorkerV8::Add(args) E:");
        WorkerV8 *workerV8 = ObjectWrap::Unwrap<WorkerV8>(args.This());

        // Validate one argument to add
        if (args.Length() != 1) {
            DBG("WorkerV8::Add(args) X: expecting one param");
            return v8::ThrowException(v8::String::New("Add has no parameter"));
        }
        ArgInfo *ai = workerV8->ObtainArgInfo();
        ai->js_this = v8::Persistent<v8::Object>::New( args.This() );
        ai->value = v8::Persistent<v8::Value>::New( args[0] );

        workerV8->handler_->Add(ai);
        DBG("WorkerV8::Add(args) X:");
        return v8::Undefined();
    }

    static v8::Handle<v8::Value> AddDelayed(const v8::Arguments& args) {
        DBG("WorkerV8::AddDelayed(args) E:");
        WorkerV8 *workerV8 = ObjectWrap::Unwrap<WorkerV8>(args.This());

        // Validate two argument to addDelayed
        if (args.Length() != 2) {
            DBG("WorkerV8::AddDelayed(args) X: expecting two params");
            return v8::ThrowException(v8::String::New("AddDelayed expects req delayTime params"));
        }
        ArgInfo *ai = workerV8->ObtainArgInfo();
        ai->js_this = v8::Persistent<v8::Object>::New( args.This() );
        ai->value = v8::Persistent<v8::Value>::New( args[0] );
        v8::Handle<v8::Value> v8DelayMs(args[1]->ToObject());
        int32_t delay_ms = v8DelayMs->Int32Value();
        workerV8->handler_->AddDelayed(ai, delay_ms);

        DBG("WorkerV8::AddDelayed(args) X:");
        return v8::Undefined();
    }

    static v8::Handle<v8::Value> NewWorkerV8(const v8::Arguments& args) {
        DBG("WorkerV8::NewWorkerV8 E: args.Length()=%d", args.Length());
        WorkerV8 *worker = new WorkerV8(args.This(), args[0]);
        DBG("WorkerV8::NewWorkerV8 X:");
        return worker->handle_;
    }
};

void WorkerV8Init() {
    DBG("WorkerV8Init E:");
    v8::HandleScope handle_scope;

    WorkerV8Template = v8::Persistent<v8::FunctionTemplate>::New(
                           v8::FunctionTemplate::New(WorkerV8::NewWorkerV8));
    WorkerV8Template->SetClassName(v8::String::New("Worker"));
    // native self (Field 0 is handle_) field count is at least 1
    WorkerV8Template->InstanceTemplate()->SetInternalFieldCount(1);

    // Set prototype methods
    SET_PROTOTYPE_METHOD(WorkerV8Template, "run", WorkerV8::Run);
    SET_PROTOTYPE_METHOD(WorkerV8Template, "add", WorkerV8::Add);
    SET_PROTOTYPE_METHOD(WorkerV8Template, "addDelayed", WorkerV8::AddDelayed);

    DBG("WorkerV8Init X:");
}

void testWorkerV8(v8::Handle<v8::Context> context) {
    ALOGD("testWorkerV8 E: ********");
    v8::HandleScope handle_scope;

    v8::TryCatch try_catch;
    try_catch.SetVerbose(true);

    ALOGD("testWorkerV8 runJs");
    runJs(context, &try_catch, "local-string",
        "var w1 = new Worker(function (msg) {"
        "     print('w1: ' + msg);\n"
        "});\n"
        "w1.run();\n"
        "var w2 = new Worker(function (msg) {"
        "     print('w2: ' + msg);\n"
        "});\n"
        "w2.run();\n"
        "w2.addDelayed('three', 1000);\n"
        "w2.add('one');\n"
        "w1.add('two');\n"
        "w1.addDelayed('four', 2000);\n"
    );
    ALOGD("testWorkerV8 X: ********");
}

extern void WorkerV8ObjectTemplateInit(v8::Handle<v8::ObjectTemplate> target) {
    DBG("WorkerV8ObjectTemplateInit(target) E:");
    target->Set(v8::String::New("Worker"), WorkerV8Template);
    DBG("WorkerV8ObjectTemplateInit(target) X:\n");
}
