/*
 * Copyright (C) 2006, 2007, 2008, 2010 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 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.
 */

#import "WebElementDictionary.h"

#import "DOMNodeInternal.h"
#import "WebDOMOperations.h"
#import "WebFrame.h"
#import "WebFrameInternal.h"
#import "WebKitLogging.h"
#import "WebTypesInternal.h"
#import "WebView.h"
#import "WebViewPrivate.h"
#import <JavaScriptCore/InitializeThreading.h>
#import <WebCore/DragController.h>
#import <WebCore/Frame.h>
#import <WebCore/HitTestResult.h>
#import <WebCore/Image.h>
#import <WebCore/WebCoreObjCExtras.h>
#import <WebKitLegacy/DOMCore.h>
#import <WebKitLegacy/DOMExtensions.h>
#import <wtf/MainThread.h>
#import <wtf/RunLoop.h>

using namespace WebCore;

static CFMutableDictionaryRef lookupTable = NULL;

static void addLookupKey(NSString *key, SEL selector)
{
    CFDictionaryAddValue(lookupTable, (__bridge CFStringRef)key, selector);
}

static void cacheValueForKey(const void *key, const void *value, void *self)
{
    // calling objectForKey will cache the value in our _cache dictionary
    [(__bridge WebElementDictionary *)self objectForKey:(__bridge NSString *)key];
}

@implementation WebElementDictionary

+ (void)initialize
{
#if !PLATFORM(IOS_FAMILY)
    JSC::initializeThreading();
    WTF::initializeMainThreadToProcessMainThread();
    RunLoop::initializeMainRunLoop();
#endif
}

+ (void)initializeLookupTable
{
    if (lookupTable)
        return;

    lookupTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL);

    addLookupKey(WebElementDOMNodeKey, @selector(_domNode));
    addLookupKey(WebElementFrameKey, @selector(_webFrame));
    addLookupKey(WebElementImageAltStringKey, @selector(_altDisplayString));
#if !PLATFORM(IOS_FAMILY)
    addLookupKey(WebElementImageKey, @selector(_image));
    addLookupKey(WebElementImageRectKey, @selector(_imageRect));
#endif
    addLookupKey(WebElementImageURLKey, @selector(_absoluteImageURL));
    addLookupKey(WebElementIsSelectedKey, @selector(_isSelected));
    addLookupKey(WebElementMediaURLKey, @selector(_absoluteMediaURL));
    addLookupKey(WebElementSpellingToolTipKey, @selector(_spellingToolTip));
    addLookupKey(WebElementTitleKey, @selector(_title));
    addLookupKey(WebElementLinkURLKey, @selector(_absoluteLinkURL));
    addLookupKey(WebElementLinkTargetFrameKey, @selector(_targetWebFrame));
    addLookupKey(WebElementLinkTitleKey, @selector(_titleDisplayString));
    addLookupKey(WebElementLinkLabelKey, @selector(_textContent));
    addLookupKey(WebElementLinkIsLiveKey, @selector(_isLiveLink));
    addLookupKey(WebElementIsContentEditableKey, @selector(_isContentEditable));
    addLookupKey(WebElementIsInScrollBarKey, @selector(_isInScrollBar));
}

- (id)initWithHitTestResult:(const HitTestResult&)result
{
    [[self class] initializeLookupTable];
    self = [super init];
    if (!self)
        return nil;
    _result = new HitTestResult(result);
    return self;
}

- (void)dealloc
{
    if (WebCoreObjCScheduleDeallocateOnMainThread([WebElementDictionary class], self))
        return;

    delete _result;
    [_cache release];
    [_nilValues release];
    [super dealloc];
}

- (void)_fillCache
{
    CFDictionaryApplyFunction(lookupTable, cacheValueForKey, (__bridge void*)self);
    _cacheComplete = YES;
}

- (NSUInteger)count
{
    if (!_cacheComplete)
        [self _fillCache];
    return [_cache count];
}

- (NSEnumerator *)keyEnumerator
{
    if (!_cacheComplete)
        [self _fillCache];
    return [_cache keyEnumerator];
}

- (id)objectForKey:(id)key
{
    id value = [_cache objectForKey:key];
    if (value || _cacheComplete || [_nilValues containsObject:key])
        return value;

    SEL selector = static_cast<SEL>(const_cast<void*>(CFDictionaryGetValue(lookupTable, (__bridge CFTypeRef)key)));
    if (!selector)
        return nil;
    value = [self performSelector:selector];

    NSUInteger lookupTableCount = CFDictionaryGetCount(lookupTable);
    if (value) {
        if (!_cache)
            _cache = [[NSMutableDictionary alloc] initWithCapacity:lookupTableCount];
        [_cache setObject:value forKey:key];
    } else {
        if (!_nilValues)
            _nilValues = [[NSMutableSet alloc] initWithCapacity:lookupTableCount];
        [_nilValues addObject:key];
    }

    _cacheComplete = ([_cache count] + [_nilValues count]) == lookupTableCount;

    return value;
}

- (DOMNode *)_domNode
{
    return kit(_result->innerNonSharedNode());
}

- (WebFrame *)_webFrame
{
    return [[[self _domNode] ownerDocument] webFrame];
}

// String's NSString* operator converts null Strings to empty NSStrings for compatibility
// with AppKit. We need to work around that here.
static NSString* NSStringOrNil(String coreString)
{
    if (coreString.isNull())
        return nil;
    return coreString;
}

- (NSString *)_altDisplayString
{
    return NSStringOrNil(_result->altDisplayString());
}

- (NSString *)_spellingToolTip
{
    TextDirection dir;
    return NSStringOrNil(_result->spellingToolTip(dir));
}

#if !PLATFORM(IOS_FAMILY)

- (NSImage *)_image
{
    Image* image = _result->image();
    return image ? image->nsImage() : nil;
}

- (NSValue *)_imageRect
{
    IntRect rect = _result->imageRect();
    return rect.isEmpty() ? nil : [NSValue valueWithRect:rect];
}

#endif

- (NSURL *)_absoluteImageURL
{
    return _result->absoluteImageURL();
}

- (NSURL *)_absoluteMediaURL
{
    return _result->absoluteMediaURL();
}

- (NSNumber *)_isSelected
{
    return [NSNumber numberWithBool:_result->isSelected()];
}

- (NSString *)_title
{
    TextDirection dir;
    return NSStringOrNil(_result->title(dir));
}

- (NSURL *)_absoluteLinkURL
{
    return _result->absoluteLinkURL();
}

- (WebFrame *)_targetWebFrame
{
    return kit(_result->targetFrame());
}

- (NSString *)_titleDisplayString
{
    return NSStringOrNil(_result->titleDisplayString());
}

- (NSString *)_textContent
{
    return NSStringOrNil(_result->textContent());
}

- (NSNumber *)_isLiveLink
{
    Element* urlElement = _result->URLElement();
    return [NSNumber numberWithBool:(urlElement && isDraggableLink(*urlElement))];
}

- (NSNumber *)_isContentEditable
{
    return [NSNumber numberWithBool:_result->isContentEditable()];
}

- (NSNumber *)_isInScrollBar
{
    return [NSNumber numberWithBool:_result->scrollbar() != 0];
}

@end
