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

#import "PSAlarmsController.h"
#import "PSAlarm.h"
#import "PSAlerts.h"
#import "NSString-NJRExtensions.h"
#import "NSTableView-NJRExtensions.h"
#import "NJRTableView.h"
#import "NJRTableDelegate.h"

@interface PSAlarmsController (PrivateUndoSupport)

- (void)_restoreAlarms:(NSSet *)selectedAlarms;
- (void)_removeAlarms:(NSSet *)selectedAlarms;

@end

@implementation PSAlarmsController

- (void)alarmsChanged;
{
    reorderedAlarms = [[alarmList delegate] reorderedDataForData: [alarms alarms]];
}

- (id)init;
{
    if ( (self = [super initWithWindowNibName: @"Alarms"]) != nil) {
        alarms = [PSAlarms allAlarms];
        // XXX workaround for bug in 10.2.1, 10.1.5: autosave name set in IB doesn't show up
        [self setWindowFrameAutosaveName: @"Pester alarm list"];
        // Apple documents the NSUserDefaults key, so we can rely on it hopefully.
        if (nil == [[NSUserDefaults standardUserDefaults] objectForKey:
            [@"NSWindow Frame " stringByAppendingString: [[self window] frameAutosaveName]]])
           {
            [[self window] center];
           }
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(alarmsChanged) name: PSAlarmsDidChangeNotification object: alarms];
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(tableViewSelectionDidChange:) name: NSTableViewSelectionDidChangeNotification object: alarmList];
        messageAttributes = [[NSDictionary alloc] initWithObjectsAndKeys: [[[alarmList tableColumnWithIdentifier: @"message"] dataCell] font], NSFontAttributeName, nil];
        [alarmList setAutosaveName: @"Alarm list"];
        [alarmList setAutosaveTableColumns: YES];
        [self alarmsChanged];
        [[self window] makeFirstResponder: alarmList];
        [[self window] setResizeIncrements: NSMakeSize(1, [alarmList cellHeight])];
    }
    return self;
}

- (void)dealloc;
{
    [reorderedAlarms release];
    [messageAttributes release];
    [super dealloc];
}

- (NSUndoManager *)undoManager;
{
    return [[self window] undoManager];
}

- (void)_restoreAlarms:(NSSet *)selectedAlarms;
{
    [alarms restoreAlarms: selectedAlarms];
    [[alarmList delegate] selectItems: selectedAlarms];
    [[self undoManager] setActionName: NSLocalizedString(@"Alarm Removal", "Undo action")];
    [[[self undoManager] prepareWithInvocationTarget: self] _removeAlarms: selectedAlarms];
}

- (void)_removeAlarms:(NSSet *)selectedAlarms;
{
    [alarms removeAlarms: selectedAlarms];
    [[self undoManager] setActionName: NSLocalizedString(@"Alarm Removal", "Undo action")];
    [[[self undoManager] prepareWithInvocationTarget: self] _restoreAlarms: selectedAlarms];
}

- (IBAction)remove:(id)sender;
{
    [self _removeAlarms: [[alarmList delegate] selectedItems]];
}

@end

@implementation PSAlarmsController (NSTableDataSource)

- (int)numberOfRowsInTableView:(NSTableView *)tableView;
{
    return [alarms alarmCount];
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row;
{
    PSAlarm *alarm = [reorderedAlarms objectAtIndex: row];

    if ([[tableColumn identifier] isEqualToString: @"message"]) {
        NSMutableString *message = [[alarm message] mutableCopy];
        [message truncateToWidth: [tableView frameOfCellAtColumn: 0 row: row].size.width by: NSLineBreakByTruncatingTail withAttributes: messageAttributes];
        return [message autorelease];
    } else {
        NSCalendarDate *date = [alarm date];
        if ([[tableColumn identifier] isEqualToString: @"date"]) return [alarm shortDateString];
        if ([[tableColumn identifier] isEqualToString: @"time"]) {
            if (date == nil) return @"«expired»";
            return [alarm timeString];
        }
    }
    return nil;
}
@end

@implementation PSAlarmsController (NJRTableViewDataSource)

- (void)removeSelectedRowsFromTableView:(NSTableView *)aTableView;
{
    [self remove: aTableView];
}

- (NSString *)tableView:(NSTableView *)aTableView toolTipForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex;
{
    PSAlarm *alarm = [reorderedAlarms objectAtIndex: rowIndex];

    return [[alarm prettyDescription] string];
}

@end

@implementation PSAlarmsController (NSTableViewNotifications)

- (void)tableViewSelectionDidChange:(NSNotification *)aNotification;
{
    [removeButton setEnabled: ([alarmList numberOfSelectedRows] != 0)];
}

@end

@implementation PSAlarmsController (NSWindowDelegate)

// XXX workaround for bug in 10.1.5, 10.2.1 (and earlier?): no autosave on window move
- (void)windowDidMove:(NSNotification *)aNotification
{
    NSString *autosaveName = [[self window] frameAutosaveName];
    // on initial display, we get a notification inside -[NSWindow setFrameAutosaveName]!
    if (autosaveName != nil) {
        [[self window] saveFrameUsingName: autosaveName];
    }
}

- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)defaultFrame;
{
    NSWindow *window = [alarmList window];
    NSRect frame = [window frame];
    NSScrollView *scrollView = [alarmList enclosingScrollView];
    float displayedHeight = [[scrollView contentView] bounds].size.height;
    float heightChange = [[scrollView documentView] bounds].size.height - displayedHeight;
    float heightExcess;

    if (heightChange >= 0 && heightChange <= 1) {
        // either the window is already optimal size, or it's too big
        float rowHeight = [alarmList cellHeight];
        heightChange = (rowHeight * [alarmList numberOfRows]) - displayedHeight;
    }

    frame.size.height += heightChange;

    if ( (heightExcess = [window minSize].height - frame.size.height) > 1 ||
         (heightExcess = [window maxSize].height - frame.size.height) < 1) {
        heightChange += heightExcess;
        frame.size.height += heightExcess;
    }

    frame.origin.y -= heightChange;

    return frame;
}

@end