//
//  PSApplication.m
//  Pester
//
//  Created by Nicholas Riley on Fri Oct 11 2002.
//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
//

#import "PSApplication.h"
#import "PSAlarmSetController.h"
#import "PSAlarmAlertController.h"
#import "PSAlarmsController.h"
#import "PSAlarm.h"
#import "PSAlarms.h"

@implementation PSApplication

- (void)finishLaunching;
{
    appIconImage = [[NSImage imageNamed: @"NSApplicationIcon"] retain];
    [[NSNotificationCenter defaultCenter] addObserver: [PSAlarmAlertController class] selector: @selector(controllerWithTimerExpiredNotification:) name: PSAlarmTimerExpiredNotification object: nil];
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(nextAlarmDidChange:) name: PSAlarmsNextAlarmDidChangeNotification object: nil];
    [PSAlarms setUp];
    [self setDelegate: self];
    [super finishLaunching];
}

- (IBAction)showHelp:(id)sender;
{
    [[NSWorkspace sharedWorkspace] openFile: [[NSBundle mainBundle] pathForResource: @"Read Me" ofType: @"rtfd"]];
}

- (IBAction)stopAlerts:(id)sender;
{
    [PSAlarmAlertController stopAlerts: sender];
}	

- (IBAction)orderFrontSetAlarmPanel:(id)sender;
{
    [NSApp activateIgnoringOtherApps: YES];
    [alarmSetController showWindow: self];
}

- (IBAction)orderFrontAlarmsPanel:(id)sender;
{
    [NSApp activateIgnoringOtherApps: YES];
    if (alarmsController == nil) {
        alarmsController = [[PSAlarmsController alloc] init];
    }
    [alarmsController showWindow: self];
}

- (void)_resetUpdateTimer;
{
    if (dockUpdateTimer != nil) {
        [dockUpdateTimer invalidate];
        [dockUpdateTimer release];
        dockUpdateInterval = 0;
        dockUpdateTimer = nil;
    }
}

- (void)_setUpdateTimerForInterval:(NSTimeInterval)interval alarm:(PSAlarm *)alarm repeats:(BOOL)repeats;
{
    dockUpdateTimer = [NSTimer scheduledTimerWithTimeInterval: interval target: self selector: @selector(_updateDockTile:) userInfo: alarm repeats: repeats];
    [dockUpdateTimer retain];
    dockUpdateInterval = interval; // because [timer timeInterval] always returns 0 once set
}

- (void)_updateDockTile:(NSTimer *)timer;
{
    PSAlarm *alarm = [timer userInfo];
    NSTimeInterval alarmInterval;
    NSString *tileString;
    if (timer == nil) alarm = [[PSAlarms allAlarms] nextAlarm];
    if (alarm == nil) return;
    tileString = [alarm timeRemainingString];
    {
        NSMutableDictionary *atts = [NSMutableDictionary dictionary];
        NSSize imageSize = [appIconImage size];
        NSImage *tile = [[NSImage alloc] initWithSize: imageSize];
        NSSize textSize;
        NSPoint textOrigin;
        NSRect frameRect;
        float fontSize = 37;
        
        do {
            fontSize -= 1;
            [atts setObject: [NSFont boldSystemFontOfSize: fontSize] forKey: NSFontAttributeName];
            textSize = [tileString sizeWithAttributes: atts];
        } while (textSize.width > imageSize.width - 8);

        textOrigin = NSMakePoint(imageSize.width / 2 - textSize.width / 2,
                                 imageSize.height / 2 - textSize.height / 2);
        frameRect = NSInsetRect(NSMakeRect(textOrigin.x, textOrigin.y, textSize.width, textSize.height),
                                -4, -2);
        
        [tile lockFocus];
        // draw the grayed-out app icon
        [appIconImage dissolveToPoint: NSZeroPoint fraction: 0.5];
        // draw the frame
        [[NSColor colorWithCalibratedWhite: 0.1 alpha: 0.5] set];
        NSRectFill(frameRect);
        // draw a gray two-pixel text shadow
        [atts setObject: [NSColor grayColor] forKey: NSForegroundColorAttributeName];
        textOrigin.x++; textOrigin.y--;
        [tileString drawAtPoint: textOrigin withAttributes: atts];
        textOrigin.x++; textOrigin.y--;
        [tileString drawAtPoint: textOrigin withAttributes: atts];
        // draw white text
        textOrigin.x -= 2; textOrigin.y += 2;
        [atts setObject: [NSColor whiteColor] forKey: NSForegroundColorAttributeName];
        [tileString drawAtPoint: textOrigin withAttributes: atts];
        
        [tile unlockFocus];
        [NSApp setApplicationIconImage: tile];
        [tile release];
    }
    alarmInterval = [alarm interval];
    // NSLog(@"_updateDockTile > time remaining %@ (%.0lf), last time interval %.0lf", tileString, alarmInterval, dockUpdateInterval);
    if (alarmInterval > 61) {
        NSTimeInterval nextUpdate = ((unsigned long long)alarmInterval) % 60;
        if (nextUpdate <= 1) nextUpdate = 60;
        [self _resetUpdateTimer];
        [self _setUpdateTimerForInterval: nextUpdate alarm: alarm repeats: NO];
        // NSLog(@"_updateDockTile > set timer for %.0lf seconds", nextUpdate);
    } else if (timer == nil || dockUpdateInterval > 1) {
        [self _resetUpdateTimer];
        [self _setUpdateTimerForInterval: 1 alarm: alarm repeats: YES];
        // NSLog(@"_updateDockTile > set timer for 1 second");
    } else if (alarmInterval < 2) {
        [self _resetUpdateTimer];
    }
}

- (void)nextAlarmDidChange:(NSNotification *)notification;
{
    PSAlarm *nextAlarm = [notification object];
    // NSLog(@"nextAlarmDidChange: %@", nextAlarm);
    [self _resetUpdateTimer];
    if (nextAlarm == nil) {
        [NSApp setApplicationIconImage: appIconImage];
    } else {
        [self _updateDockTile: nil];
    }
}

@end

@implementation PSApplication (NSApplicationDelegate)

- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag;
{
    if (!flag) [alarmSetController showWindow: self];
    return YES;
}

- (NSMenu *)applicationDockMenu:(NSApplication *)sender;
{
    NSMenu *dockMenu = [[NSMenu alloc] initWithTitle: @""];
    PSAlarms *alarms = [PSAlarms allAlarms];
    PSAlarm *nextAlarm = [alarms nextAlarm];
    NSMenuItem *item;
    if (nextAlarm == nil) {
        [dockMenu addItemWithTitle: @"No Pending Alarms" action: nil keyEquivalent: @""];
    } else {
        [dockMenu addItemWithTitle: @"Next Alarm" action: nil keyEquivalent: @""];
        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   %@", [nextAlarm message]] action: nil keyEquivalent: @""];
        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   %@ %@", [nextAlarm shortDateString], [nextAlarm timeString]] action: nil keyEquivalent: @""];
        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   Remaining: %@", [nextAlarm timeRemainingString]] action: nil keyEquivalent: @""];
    }
    [dockMenu addItem: [NSMenuItem separatorItem]];
    item = [dockMenu addItemWithTitle: @"Set AlarmÉ" action: @selector(orderFrontSetAlarmPanel:) keyEquivalent: @""];
    [item setTarget: self];
    item = [dockMenu addItemWithTitle: [NSString stringWithFormat: @"All Alarms (%d)É", [alarms alarmCount]] action: @selector(orderFrontAlarmsPanel:) keyEquivalent: @""];
    [item setTarget: self];
    return [dockMenu autorelease];
}

@end

@implementation PSApplication (NSApplicationNotifications)

- (void)applicationWillTerminate:(NSNotification *)notification;
{
    [NSApp setApplicationIconImage: appIconImage];
}

@end
