//
//  DockCamPrefs.m
//  DockCam
//
//  Created by Nicholas Riley on Thu Jun 27 2002.
//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
//

#import "DockCamPrefs.h"

NSString * const DCImageLocation = @"DCImageLocation";
NSString * const DCImageSize = @"DCImageSize";
NSString * const DCImageRefreshEnabled = @"DCImageRefreshEnabled";
NSString * const DCImageRefreshInterval = @"DCImageRefreshInterval";
NSString * const DCShowImageInBackground = @"DCShowImageInBackground";
NSString * const DCShowStatus = @"DCShowStatus";

NSString * const DCPrefChangedNotification = @"DCPrefChangedNotification";

const NSTimeInterval DCDefaultImageRefreshInterval = 30;

enum {
    DCImageRetrieveOnOpen = 2000, DCImageRetrieveOnTimer = 2001
};

enum {
    DCImageRefreshIntervalSeconds = 1, DCImageRefreshIntervalMinutes = 60, DCImageRefreshIntervalHours = 3600
};

NSUserDefaults *defaults;

@implementation DockCamPrefs

+ (void)initialize;
{
    NSDictionary *appDefaults =
        [NSDictionary dictionaryWithObjectsAndKeys:
            @"", DCImageLocation,
            [NSNumber numberWithInt: DCDefaultImageRefreshInterval], DCImageRefreshInterval,
            [NSNumber numberWithBool: NO], DCShowImageInBackground,
            [NSNumber numberWithBool: YES], DCShowStatus,
           nil];
    defaults = [NSUserDefaults standardUserDefaults];
    [defaults registerDefaults: appDefaults];
}

+ (void)_prefChanged:(NSString *)pref;
{
    [[NSNotificationCenter defaultCenter] postNotificationName: DCPrefChangedNotification object: pref];
}

#pragma mark preference getters

+ (BOOL)boolForPref:(NSString *)pref;
{
    return [defaults boolForKey: pref];
}

+ (int)intForPref:(NSString *)pref;
{
    return [defaults integerForKey: pref];
}

+ (NSString *)stringForPref:(NSString *)pref;
{
    return [defaults stringForKey: pref];
}

+ (NSSize)sizeForPref:(NSString *)pref;
{
    return NSSizeFromString([defaults stringForKey: pref]);
}

#pragma mark preference setters

+ (void)setBool:(BOOL)value forPref:(NSString *)pref;
{
    BOOL oldValue = [self boolForPref: pref];
    if (oldValue != value) {
        [defaults setBool: value forKey: pref];
        [self _prefChanged: pref];
    }
}

+ (void)setInt:(int)value forPref:(NSString *)pref;
{
    int oldValue = [self intForPref: pref];
    if (oldValue != value) {
        [defaults setInteger: value forKey: pref];
        [self _prefChanged: pref];
    }
}

+ (void)setString:(NSString *)value forPref:(NSString *)pref;
{
    NSString *oldValue = [self stringForPref: pref];
    if (![oldValue isEqualToString: value]) {
        [defaults setObject: value forKey: pref];
        [self _prefChanged: pref];
    }
}

+ (void)setSize:(NSSize)value forPref:(NSString *)pref;
{
    NSSize oldValue = [self sizeForPref: pref];
    if (!NSEqualSizes(oldValue, value)) {
        [defaults setObject: NSStringFromSize(value) forKey: pref];
        [self _prefChanged: pref];
    }
}

#pragma mark complex interface-preference mapping

- (BOOL)retrieveOnTimer;
{
    return [[retrieveImageAutomatically selectedCell] tag] == DCImageRetrieveOnTimer;
}

- (NSTimeInterval)interval;
{
    return [imageRefreshInterval intValue] * [[imageRefreshIntervalUnits selectedItem] tag];
}

- (void)setInterval:(NSTimeInterval)interval;
{
    // we assume that the tags are in ascending order in the array
    NSEnumerator *e = [[imageRefreshIntervalUnits itemArray] reverseObjectEnumerator];
    NSMenuItem *i;
    int multiplierTag;
    
    while ( (i = [e nextObject]) != nil) {
        multiplierTag = [i tag];
        if (((int)interval % multiplierTag) == 0) {
            [imageRefreshInterval setIntValue: interval / multiplierTag];
            [imageRefreshIntervalUnits selectItem: i];
            return;
        }
    }
    [imageRefreshIntervalUnits selectItemAtIndex: 0];
    [imageRefreshInterval setIntValue: DCDefaultImageRefreshInterval];
}

#pragma mark preference I/O

- (void)readFromPrefs;
{
    [imageLocation setStringValue: [DockCamPrefs stringForPref: DCImageLocation]];
    [retrieveImageAutomatically selectCellWithTag:
        [DockCamPrefs boolForPref: DCImageRefreshEnabled] ? DCImageRetrieveOnTimer : DCImageRetrieveOnOpen];
    [self setInterval: [DockCamPrefs intForPref: DCImageRefreshInterval]];
    [showImageInBackground setState:
        [DockCamPrefs boolForPref: DCShowImageInBackground] ? NSOnState : NSOffState];
}

- (IBAction)writeToPrefs:(id)sender;
{
    [DockCamPrefs setString: [imageLocation stringValue] forPref: DCImageLocation];
    [DockCamPrefs setBool: [self retrieveOnTimer] forPref: DCImageRefreshEnabled];
    [DockCamPrefs setInt: [self interval] forPref: DCImageRefreshInterval];
    [DockCamPrefs setBool: [showImageInBackground state] == NSOnState forPref: DCShowImageInBackground];
    [defaults synchronize];
}

#pragma mark interface maintenance

- (IBAction)showWindow:(id)sender;
{
    // XXX workaround for weird bug where combo box and text field alternately become first responder
    [super showWindow: sender];
    [[[self window] initialFirstResponder] becomeFirstResponder];
}

- (void)update;
{
    BOOL enabled = [self retrieveOnTimer];
    [imageRefreshInterval setEnabled: enabled];
    [imageRefreshIntervalUnits setEnabled: enabled];
}

- (IBAction)retrieveImageAutomatically:(id)sender;
{
    [self update];
    if ([self retrieveOnTimer]) [imageRefreshInterval becomeFirstResponder];
    else [sender becomeFirstResponder];
}

#pragma mark initialize-release

- (id)init {
    self = [super initWithWindowNibName:@"Preferences"];
    [self window]; // connect outlets
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowWillClose:)
                                                 name: NSWindowWillCloseNotification object: [self window]];
    [self readFromPrefs];
    [self update];
    return self;
}

@end

@implementation DockCamPrefs (NSWindowNotifications)

- (void)windowWillClose:(NSNotification *)notification;
{
    [self writeToPrefs: self];
}

@end