//
// Object.cpp
//

#define DBG_LEVEL 0
#include <Raym/Log.h>
#include <Raym/Object.h>
#include <Raym/String.h>
#include <Raym/AutoreleasePool.h>

namespace Raym
{

#ifdef RAYM_MEMORY_CHECK
int global_raym_count_ = 0;
int global_raym_init_count_ = 0;
int global_raym_retain_count_ = 0;
int global_raym_autorelease_count_ = 0;
int global_raym_release_count_ = 0;
DEFINE_STATIC_MUTEX(global_lock_);
#endif

Object::Object()
{
    DebugLog2("Object::Object()");

    RAYM_LOCK_CREATE;
    RAYM_COND_CREATE;

    _retainCount = 1;

#ifdef RAYM_MEMORY_CHECK
    global_lock_.lock();
    ++global_raym_count_;
//    DebugLog0("C:0x%08x:%d", this, global_raym_count_);
    global_lock_.unlock();
#endif
}

Object::~Object()
{
    RAYM_LOCK_DESTROY;

#ifdef RAYM_MEMORY_CHECK
    global_lock_.lock();
//    DebugLog0("D:0x%08x:%d", this, global_raym_count_);
    --global_raym_count_;
    global_lock_.unlock();
#endif

    DebugLog2("Object::~Object()");
}

Object *Object::alloc()
{
    DebugLog2("Object::alloc()");

    return new Object();
}

Object *Object::init()
{
    DebugLog2("Object::init()");

#ifdef RAYM_MEMORY_CHECK
    global_lock_.lock();
    ++global_raym_init_count_;
    global_lock_.unlock();
#endif

    return this;
}

Object *Object::retain()
{
    DebugLog2("Object::retain()");

    RaymLock(this);
    ++_retainCount;
    RaymUnlock(this);

#ifdef RAYM_MEMORY_CHECK
    global_lock_.lock();
    ++global_raym_retain_count_;
    global_lock_.unlock();
#endif

    return this;
}

Object *Object::autorelease()
{
    DebugLog2("Object::autorelease()");

#ifdef RAYM_MEMORY_CHECK
    global_lock_.lock();
    ++global_raym_autorelease_count_;
    global_lock_.unlock();
#endif

    AutoreleasePool::addObject(this);
    return this;
}

Object *Object::autorelease(bool rootPool)
{
    DebugLog2("Object::autorelease()");

#ifdef RAYM_MEMORY_CHECK
    global_lock_.lock();
    ++global_raym_autorelease_count_;
    global_lock_.unlock();
#endif

    AutoreleasePool::addObject(this, rootPool);
    return this;
}

void Object::release()
{
    DebugLog2("Object::release()");

#ifdef RAYM_MEMORY_CHECK
    global_lock_.lock();
    ++global_raym_release_count_;
    global_lock_.unlock();
#endif

    RaymLock(this);
    if (_retainCount > 0)
    {
        --_retainCount;
        if (_retainCount == 0)
        {
            RaymUnlock(this);
            delete this;
            return;
        }
    }
    else
    {
        DebugLog0("object is already released. (0x%016lx)", this);
        abort();
    }
    RaymUnlock(this);
}

String *Object::description()
{
    return String::stringWithFormat("<%s:0x%016lx>", className(), this);
}

const char *Object::className()
{
    return "Object";
}


} // Raym
