/*
 * Copyright (C) 2005 Apple Computer, 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.
 */

#import <WebKit/WebNSUserDefaultsExtras.h>

#import <JavaScriptCore/Assertions.h>
#import <WebKitSystemInterface.h>

@implementation NSString (WebNSUserDefaultsPrivate)

- (NSString *)_webkit_HTTPStyleLanguageCode
{
    // Look up the language code using CFBundle.
    NSString *languageCode = self;
    NSString *preferredLanguageCode = [(id)WKCopyCFLocalizationPreferredName((CFStringRef)self) autorelease];

    if (preferredLanguageCode)
        languageCode = preferredLanguageCode;
    
    // Make the string lowercase.
    NSString *lowercaseLanguageCode = [languageCode lowercaseString];
    
    // Turn a '_' into a '-' if it appears after a 2-letter language code.
    if ([lowercaseLanguageCode length] < 3 || [lowercaseLanguageCode characterAtIndex:2] != '_') {
        return lowercaseLanguageCode;
    }
    NSMutableString *result = [lowercaseLanguageCode mutableCopy];
    [result replaceCharactersInRange:NSMakeRange(2, 1) withString:@"-"];
    return [result autorelease];
}

@end

@implementation NSUserDefaults (WebNSUserDefaultsExtras)

static NSString *preferredLanguageCode = nil;
static NSLock *preferredLanguageLock = nil;
static pthread_once_t preferredLanguageLockOnce = PTHREAD_ONCE_INIT;
static pthread_once_t addDefaultsChangeObserverOnce = PTHREAD_ONCE_INIT;

static void makeLock(void)
{
    preferredLanguageLock = [[NSLock alloc] init]; 
}

+ (void)_webkit_ensureAndLockPreferredLanguageLock
{
    pthread_once(&preferredLanguageLockOnce, makeLock);
    [preferredLanguageLock lock];
}

+ (void)_webkit_defaultsDidChange
{
    [self _webkit_ensureAndLockPreferredLanguageLock];

    [preferredLanguageCode release];
    preferredLanguageCode = nil;

    [preferredLanguageLock unlock];
}

static void addDefaultsChangeObserver(void)
{
    [[NSNotificationCenter defaultCenter] addObserver:[NSUserDefaults class]
                                             selector:@selector(_webkit_defaultsDidChange)
                                                 name:NSUserDefaultsDidChangeNotification
                                               object:[NSUserDefaults standardUserDefaults]];
}

+ (void)_webkit_addDefaultsChangeObserver
{
    pthread_once(&addDefaultsChangeObserverOnce, addDefaultsChangeObserver);
}

+ (NSString *)_webkit_preferredLanguageCode
{
    // Get this outside the lock since it might block on the defaults lock, while we are inside registerDefaults:.
    NSUserDefaults *standardDefaults = [self standardUserDefaults];

    BOOL addObserver = NO;

    [self _webkit_ensureAndLockPreferredLanguageLock];

    if (!preferredLanguageCode) {
        NSArray *languages = [standardDefaults stringArrayForKey:@"AppleLanguages"];
        if ([languages count] == 0) {
            preferredLanguageCode = [@"en" retain];
        } else {
            preferredLanguageCode = [[[languages objectAtIndex:0] _webkit_HTTPStyleLanguageCode] copy];
        }
        addObserver = YES;
    }

    NSString *code = [[preferredLanguageCode retain] autorelease];
    
    [preferredLanguageLock unlock];

    if (addObserver) {
        [self _webkit_addDefaultsChangeObserver];
    }

    return code;
}

@end
