/*
 * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer. 
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution. 
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "JSUtils.h"

#include "JSBase.h"
#include "JSObject.h"
#include "JSRun.h"
#include "JSValueWrapper.h"
#include "UserObjectImp.h"
#include <JavaScriptCore/JSString.h>
#include <JavaScriptCore/PropertyNameArray.h>

struct ObjectImpList {
    JSObject* imp;
    ObjectImpList* next;
    CFTypeRef data;
};

static CFTypeRef KJSValueToCFTypeInternal(JSValue inValue, ExecState *exec, ObjectImpList* inImps);
static JSGlueGlobalObject* getThreadGlobalObject();

//--------------------------------------------------------------------------
// CFStringToUString
//--------------------------------------------------------------------------

UString CFStringToUString(CFStringRef inCFString)
{
    UString result;
    if (inCFString) {
        CFIndex len = CFStringGetLength(inCFString);
        UniChar* buffer = (UniChar*)malloc(sizeof(UniChar) * len);
        if (buffer)
        {
            CFStringGetCharacters(inCFString, CFRangeMake(0, len), buffer);
            result = UString((const UChar *)buffer, len);
            free(buffer);
        }
    }
    return result;
}


//--------------------------------------------------------------------------
// UStringToCFString
//--------------------------------------------------------------------------
// Caller is responsible for releasing the returned CFStringRef
CFStringRef UStringToCFString(const UString& inUString)
{
    return CFStringCreateWithCharacters(0, (const UniChar*)inUString.data(), inUString.size());
}


//--------------------------------------------------------------------------
// CFStringToIdentifier
//--------------------------------------------------------------------------

Identifier CFStringToIdentifier(CFStringRef inCFString, ExecState* exec)
{
    return Identifier(exec, CFStringToUString(inCFString));
}


//--------------------------------------------------------------------------
// IdentifierToCFString
//--------------------------------------------------------------------------
// Caller is responsible for releasing the returned CFStringRef
CFStringRef IdentifierToCFString(const Identifier& inIdentifier)
{
    return UStringToCFString(inIdentifier.ustring());
}


//--------------------------------------------------------------------------
// KJSValueToJSObject
//--------------------------------------------------------------------------
JSUserObject* KJSValueToJSObject(JSValue inValue, ExecState *exec)
{
    JSUserObject* result = 0;

    if (inValue.isObject(&UserObjectImp::info)) {
        UserObjectImp* userObjectImp = static_cast<UserObjectImp *>(asObject(inValue));
        result = userObjectImp->GetJSUserObject();
        if (result)
            result->Retain();
    } else {
        JSValueWrapper* wrapperValue = new JSValueWrapper(inValue);
        if (wrapperValue) {
            JSObjectCallBacks callBacks;
            JSValueWrapper::GetJSObectCallBacks(callBacks);
            result = (JSUserObject*)JSObjectCreate(wrapperValue, &callBacks);
            if (!result) {
                delete wrapperValue;
            }
        }
    }
    return result;
}

//--------------------------------------------------------------------------
// JSObjectKJSValue
//--------------------------------------------------------------------------
JSValue JSObjectKJSValue(JSUserObject* ptr)
{
    JSLock lock(true);

    JSValue result = jsUndefined();
    if (ptr)
    {
        bool handled = false;

        switch (ptr->DataType())
        {
            case kJSUserObjectDataTypeJSValueWrapper:
            {
                JSValueWrapper* wrapper = (JSValueWrapper*)ptr->GetData();
                if (wrapper)
                {
                    result = wrapper->GetValue();
                    handled = true;
                }
                break;
            }

            case kJSUserObjectDataTypeCFType:
            {
                CFTypeRef cfType = (CFTypeRef*)ptr->GetData();
                if (cfType)
                {
                    CFTypeID typeID = CFGetTypeID(cfType);
                    if (typeID == CFStringGetTypeID())
                    {
                        result = jsString(getThreadGlobalExecState(), CFStringToUString((CFStringRef)cfType));
                        handled = true;
                    }
                    else if (typeID == CFNumberGetTypeID())
                    {
                        double num;
                        CFNumberGetValue((CFNumberRef)cfType, kCFNumberDoubleType, &num);
                        result = jsNumber(getThreadGlobalExecState(), num);
                        handled = true;
                    }
                    else if (typeID == CFBooleanGetTypeID())
                    {
                        result = jsBoolean(CFBooleanGetValue((CFBooleanRef)cfType));
                        handled = true;
                    }
                    else if (typeID == CFNullGetTypeID())
                    {
                        result = jsNull();
                        handled = true;
                    }
                }
                break;
            }
        }
        if (!handled)
        {
            ExecState* exec = getThreadGlobalExecState();
            result = new (exec) UserObjectImp(getThreadGlobalObject()->userObjectStructure(), ptr);
        }
    }
    return result;
}




//--------------------------------------------------------------------------
// KJSValueToCFTypeInternal
//--------------------------------------------------------------------------
// Caller is responsible for releasing the returned CFTypeRef
CFTypeRef KJSValueToCFTypeInternal(JSValue inValue, ExecState *exec, ObjectImpList* inImps)
{
    if (!inValue)
        return 0;

    CFTypeRef result = 0;

    JSLock lock(true);

        if (inValue.isBoolean())
            {
                result = inValue.toBoolean(exec) ? kCFBooleanTrue : kCFBooleanFalse;
                RetainCFType(result);
                return result;
            }

        if (inValue.isString())
            {
                UString uString = inValue.toString(exec);
                result = UStringToCFString(uString);
                return result;
            }

        if (inValue.isNumber())
            {
                double number1 = inValue.toNumber(exec);
                double number2 = (double)inValue.toInteger(exec);
                if (number1 ==  number2)
                {
                    int intValue = (int)number2;
                    result = CFNumberCreate(0, kCFNumberIntType, &intValue);
                }
                else
                {
                    result = CFNumberCreate(0, kCFNumberDoubleType, &number1);
                }
                return result;
            }

        if (inValue.isObject())
            {
                            if (inValue.isObject(&UserObjectImp::info)) {
                                UserObjectImp* userObjectImp = static_cast<UserObjectImp *>(asObject(inValue));
                    JSUserObject* ptr = userObjectImp->GetJSUserObject();
                    if (ptr)
                    {
                        result = ptr->CopyCFValue();
                    }
                }
                else
                {
                    JSObject *object = inValue.toObject(exec);
                    UInt8 isArray = false;

                    // if two objects reference each
                    JSObject* imp = object;
                    ObjectImpList* temp = inImps;
                    while (temp) {
                        if (imp == temp->imp) {
                            return CFRetain(GetCFNull());
                        }
                        temp = temp->next;
                    }

                    ObjectImpList imps;
                    imps.next = inImps;
                    imps.imp = imp;


//[...] HACK since we do not have access to the class info we use class name instead
#if 0
                    if (object->inherits(&ArrayInstanceImp::info))
#else
                    if (object->className() == "Array")
#endif
                    {
                        isArray = true;
                        JSGlueGlobalObject* globalObject = static_cast<JSGlueGlobalObject*>(exec->dynamicGlobalObject());
                        if (globalObject && (globalObject->Flags() & kJSFlagConvertAssociativeArray)) {
                            PropertyNameArray propNames(exec);
                            object->getPropertyNames(exec, propNames);
                            PropertyNameArray::const_iterator iter = propNames.begin();
                            PropertyNameArray::const_iterator end = propNames.end();
                            while(iter != end && isArray)
                            {
                                Identifier propName = *iter;
                                UString ustr = propName.ustring();
                                const UniChar* uniChars = (const UniChar*)ustr.data();
                                int size = ustr.size();
                                while (size--) {
                                    if (uniChars[size] < '0' || uniChars[size] > '9') {
                                        isArray = false;
                                        break;
                                    }
                                }
                                iter++;
                            }
                        }
                    }

                    if (isArray)
                    {
                        // This is an KJS array
                        unsigned int length = object->get(exec, Identifier(exec, "length")).toUInt32(exec);
                        result = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
                        if (result)
                        {
                            for (unsigned i = 0; i < length; i++)
                            {
                                CFTypeRef cfValue = KJSValueToCFTypeInternal(object->get(exec, i), exec, &imps);
                                CFArrayAppendValue((CFMutableArrayRef)result, cfValue);
                                ReleaseCFType(cfValue);
                            }
                        }
                    }
                    else
                    {
                        // Not an array, just treat it like a dictionary which contains (property name, property value) pairs
                        PropertyNameArray propNames(exec);
                        object->getPropertyNames(exec, propNames);
                        {
                            result = CFDictionaryCreateMutable(0,
                                                               0,
                                                               &kCFTypeDictionaryKeyCallBacks,
                                                               &kCFTypeDictionaryValueCallBacks);
                            if (result)
                            {
                                PropertyNameArray::const_iterator iter = propNames.begin();
                                PropertyNameArray::const_iterator end = propNames.end();
                                while(iter != end)
                                {
                                    Identifier propName = *iter;
                                    if (object->hasProperty(exec, propName))
                                    {
                                        CFStringRef cfKey = IdentifierToCFString(propName);
                                        CFTypeRef cfValue = KJSValueToCFTypeInternal(object->get(exec, propName), exec, &imps);
                                        if (cfKey && cfValue)
                                        {
                                            CFDictionaryAddValue((CFMutableDictionaryRef)result, cfKey, cfValue);
                                        }
                                        ReleaseCFType(cfKey);
                                        ReleaseCFType(cfValue);
                                    }
                                    iter++;
                                }
                            }
                        }
                    }
                }
                return result;
            }

    if (inValue.isUndefinedOrNull())
        {
            result = RetainCFType(GetCFNull());
            return result;
        }

    ASSERT_NOT_REACHED();
    return 0;
}

CFTypeRef KJSValueToCFType(JSValue inValue, ExecState *exec)
{
    return KJSValueToCFTypeInternal(inValue, exec, 0);
}

CFTypeRef GetCFNull(void)
{
    static CFArrayRef sCFNull = CFArrayCreate(0, 0, 0, 0);
    CFTypeRef result = JSGetCFNull();
    if (!result)
    {
        result = sCFNull;
    }
    return result;
}

/*
 * This is a slight hack. The JSGlue API has no concept of execution state.
 * However, execution state is an inherent part of JS, and JSCore requires it.
 * So, we keep a single execution state for the whole thread and supply it
 * where necessary.

 * The execution state holds two things: (1) exceptions; (2) the global object. 
 * JSGlue has no API for accessing exceptions, so we just discard them. As for
 * the global object, JSGlue includes no calls that depend on it. Its property
 * getters and setters are per-object; they don't walk up the enclosing scope. 
 * Functions called by JSObjectCallFunction may reference values in the enclosing 
 * scope, but they do so through an internally stored scope chain, so we don't 
 * need to supply the global scope.
 */      

static pthread_key_t globalObjectKey;
static pthread_once_t globalObjectKeyOnce = PTHREAD_ONCE_INIT;

static void unprotectGlobalObject(void* data) 
{
    JSLock lock(true);
    gcUnprotect(static_cast<JSGlueGlobalObject*>(data));
}

static void initializeGlobalObjectKey()
{
    pthread_key_create(&globalObjectKey, unprotectGlobalObject);
}

static JSGlueGlobalObject* getThreadGlobalObject()
{
    pthread_once(&globalObjectKeyOnce, initializeGlobalObjectKey);
    JSGlueGlobalObject* globalObject = static_cast<JSGlueGlobalObject*>(pthread_getspecific(globalObjectKey));
    if (!globalObject) {
        globalObject = new (&JSGlobalData::sharedInstance()) JSGlueGlobalObject(JSGlueGlobalObject::createStructure(jsNull()));
        gcProtect(globalObject);
        pthread_setspecific(globalObjectKey, globalObject);
    }
    return globalObject;
}

ExecState* getThreadGlobalExecState()
{
    ExecState* exec = getThreadGlobalObject()->globalExec();

    // Discard exceptions -- otherwise an exception would forestall JS 
    // evaluation throughout the thread
    exec->clearException();
    return exec;
}
