/*
 * Utilities.m
 *
 * $Header: /cvs/kfm/KerberosClients/KerberosApp/Sources/Utilities.m,v 1.7 2004/10/14 02:43:49 lxs Exp $
 *
 * Copyright 2004 Massachusetts Institute of Technology.
 * All Rights Reserved.
 *
 * Export of this software from the United States of America may
 * require a specific license from the United States Government.
 * It is the responsibility of any person or organization contemplating
 * export to obtain such a license before exporting.
 * 
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 * distribute this software and its documentation for any purpose and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of M.I.T. not be used in advertising or publicity pertaining
 * to distribution of the software without specific, written prior
 * permission.  Furthermore if you modify this software you must label
 * your software as modified software and not distribute it in such a
 * fashion that it might be confused with the original M.I.T. software.
 * M.I.T. makes no representations about the suitability of
 * this software for any purpose.  It is provided "as is" without express
 * or implied warranty.
 */

#import "Utilities.h"
#import "CacheCollection.h"
#import "Credential.h"
#import "LifetimeFormatter.h"

#define kItalicObliqueness       0.3

@implementation Utilities

// ---------------------------------------------------------------------------

+ (NSString *) stringForCCVersion: (cc_uint32) version
{
    NSString *key = @"KAppStringCredentialsVersionNone";
    
    if (version == cc_credentials_v5) {
        key = @"KAppStringCredentialsVersionV5";
    } else if (version == cc_credentials_v4) {
        key = @"KAppStringCredentialsVersionV4";        
    } else if (version == cc_credentials_v4_v5) {
        key = @"KAppStringCredentialsVersionV4V5";        
    }
    
    return NSLocalizedString (key, NULL);
}

// ---------------------------------------------------------------------------

+ (NSString *) stringForCredentialState: (int) state format: (int) format
{
    NSMutableString *string = [NSMutableString string];
    
    if (state == CredentialValid) {
        [string setString: NSLocalizedString (@"KAppStringValid", NULL)];
    } else {
        NSString *key = (state & CredentialExpired) ? @"KAppStringExpired" : @"KAppStringNotValid";
        [string setString: NSLocalizedString (key, NULL)];
        
        if (format == kLongFormat) {
            NSString *longStateString = NULL;
            
            if (state & CredentialBeforeStartTime) {
                longStateString = NSLocalizedString (@"KAppStringBeforeStartTime", NULL);
            } else if (state & CredentialNeedsValidation) {
                longStateString = NSLocalizedString (@"KAppStringNeedsValidation", NULL);            
            } else if (state & CredentialBadAddress) {
                longStateString = NSLocalizedString (@"KAppStringBadAddress", NULL);                            
            }
            
            if (longStateString != NULL) {
                NSString *longStateFormat = NSLocalizedString (@"KAppStringLongStateFormat", NULL);
                [string appendFormat: longStateFormat, longStateString];
            }
        }
    }
    
    return [NSString stringWithString: string];
}

// ---------------------------------------------------------------------------

+ (NSString *) stringForTimeRemaining: (cc_time_t) timeRemaining state: (int) state format: (int) format
{
    if (state == CredentialValid) {
        LifetimeFormatter *lifetimeFormatter = [[LifetimeFormatter alloc] initWithDisplaySeconds: NO
                                                                                     shortFormat: (format == kShortFormat)];
        NSString *string = [lifetimeFormatter stringForLifetime: timeRemaining];
        [lifetimeFormatter release];

        return string;
    } else {
        return [Utilities stringForCredentialState: state format: format];
    }
}

// ---------------------------------------------------------------------------

+ (NSDictionary *) attributesForInfoWindowWithTicketState: (int) state
{
    if (state == CredentialValid) {
        return [NSDictionary dictionary];
    } else {
        return [NSDictionary dictionaryWithObjectsAndKeys: 
            [NSColor redColor], NSForegroundColorAttributeName, NULL];
    }
}

// ---------------------------------------------------------------------------

+ (NSDictionary *) attributesForDockIcon
{
    NSMutableParagraphStyle *alignment = [[[NSMutableParagraphStyle alloc] init] autorelease];
    [alignment setParagraphStyle: [NSParagraphStyle defaultParagraphStyle]];
    [alignment setAlignment: NSLeftTextAlignment];
    
    return [NSDictionary dictionaryWithObjectsAndKeys: 
        [NSFont boldSystemFontOfSize: 22], NSFontAttributeName, 
        alignment, NSParagraphStyleAttributeName, NULL];
}

// ---------------------------------------------------------------------------

+ (NSDictionary *) attributesForMenuItemOfFontSize: (float) fontSize italic: (BOOL) isItalic
{
    NSFont *font = [NSFont menuFontOfSize: fontSize];
    NSNumber *obliqueness = [NSNumber numberWithFloat: isItalic ? kItalicObliqueness : 0.0];
    
    return [NSDictionary dictionaryWithObjectsAndKeys: 
        [NSColor blackColor], NSForegroundColorAttributeName,
        font, NSFontAttributeName, 
        obliqueness, NSObliquenessAttributeName, NULL];
}

// ---------------------------------------------------------------------------

+ (NSDictionary *) attributesForTicketColumnCellOfControlSize: (NSControlSize) controlSize 
                                                         bold: (BOOL) isBold 
                                                       italic: (BOOL) isItalic
{
    float fontSize = (controlSize == NSRegularControlSize) ? 12 : 11;
    NSFont *font = isBold ? [NSFont boldSystemFontOfSize: fontSize] : [NSFont systemFontOfSize: fontSize];

    NSMutableParagraphStyle *alignment = [[[NSMutableParagraphStyle alloc] init] autorelease];
    [alignment setParagraphStyle: [NSParagraphStyle defaultParagraphStyle]];
    [alignment setAlignment: NSLeftTextAlignment];
    
    NSNumber *obliqueness = [NSNumber numberWithFloat: isItalic ? kItalicObliqueness : 0.0];
    
    return [NSDictionary dictionaryWithObjectsAndKeys: 
        font, NSFontAttributeName, 
        alignment, NSParagraphStyleAttributeName,
        obliqueness, NSObliquenessAttributeName, NULL];
}

// ---------------------------------------------------------------------------

+ (NSDictionary *) attributesForLifetimeColumnCellOfControlSize: (NSControlSize) controlSize
                                                           bold: (BOOL) isBold 
                                                          state: (int) state
                                                  timeRemaining: (cc_time_t) timeRemaining
{
    NSColor *color = ((state == CredentialValid) && 
                      (timeRemaining > kFiveMinutes)) ? [NSColor blackColor] : [NSColor redColor];
    
    NSNumber *obliqueness = [NSNumber numberWithFloat: (state == CredentialValid) ? 0.0 : kItalicObliqueness];

    float fontSize = (controlSize == NSRegularControlSize) ? 12 : 11;
    NSFont *font = isBold ? [NSFont boldSystemFontOfSize: fontSize] : [NSFont systemFontOfSize: fontSize];
    
    NSMutableParagraphStyle *alignment = [[[NSMutableParagraphStyle alloc] init] autorelease];
    [alignment setParagraphStyle: [NSParagraphStyle defaultParagraphStyle]];
    [alignment setAlignment: NSRightTextAlignment];
    
    return [NSDictionary dictionaryWithObjectsAndKeys: 
        color, NSForegroundColorAttributeName,
        obliqueness, NSObliquenessAttributeName,
        font, NSFontAttributeName, 
        alignment, NSParagraphStyleAttributeName, NULL];
}

// ---------------------------------------------------------------------------

+ (void) synchronizeCacheMenu: (NSMenu *) menu
                     fontSize: (float) fontSize
       staticPrefixItemsCount: (int) staticPrefixItemsCount
                   headerItem: (BOOL) headerItem
            checkDefaultCache: (BOOL) checkDefaultCache
            defaultCacheIndex: (int *) defaultCacheIndex
                     selector: (SEL) selector
                       sender: (id) sender
{
    int cacheCount = [[CacheCollection sharedCacheCollection] numberOfCaches];
    int headerItemCount = (cacheCount <= 0 || headerItem) ? 1 : 0;
    int dynamicItemCount = (cacheCount > 0) ? cacheCount : 0;
    int totalItemCount = staticPrefixItemsCount + headerItemCount + dynamicItemCount;
    int headerItemIndex = staticPrefixItemsCount;
    int firstDynamicItemIndex = headerItemIndex + headerItemCount;
       
    // Remove excess dynamic items
    while ([menu numberOfItems] > totalItemCount) {
        [menu removeItemAtIndex: headerItemIndex]; 
    }

    // Add back the correct number of items
    while ([menu numberOfItems] < totalItemCount) {
        NSMenuItem *item = [[NSMenuItem alloc] initWithTitle: @"" 
                                                      action: selector
                                               keyEquivalent: @""];
        [item setTarget: sender];
        [menu insertItem: item atIndex: headerItemIndex]; 
        [item release];  // menu will retain
    }

    if (headerItemCount > 0) {
        NSString *key = (cacheCount > 0) ? @"KAppStringAvailableTickets" : @"KAppStringNoTicketsAvailable" ;
        NSDictionary *attributes = [Utilities attributesForMenuItemOfFontSize: fontSize italic: NO];
        NSAttributedString *title = [[[NSAttributedString alloc] initWithString: NSLocalizedString (key, NULL)
                                                                     attributes: attributes] autorelease];
        
        NSMenuItem *item = [menu itemAtIndex: headerItemIndex];
        [item setAttributedTitle: title];
        [item setEnabled: NO];
        [item setState: NSOffState];
    }

    if (cacheCount > 0) {
        int i;

        for (i = firstDynamicItemIndex; i < (firstDynamicItemIndex + dynamicItemCount); i++) {
            NSMenuItem *item = [menu itemAtIndex: i];            
            Cache *cache = [[CacheCollection sharedCacheCollection] cacheAtIndex: (i - firstDynamicItemIndex)];
            if (cache != NULL) {
                BOOL isDefaultCache = [cache isDefault];
                int itemState = (checkDefaultCache && isDefaultCache) ? NSOnState : NSOffState;
                NSAttributedString *title = [cache stringValueForMenuWithFontSize: fontSize];

                if (isDefaultCache && (defaultCacheIndex != NULL)) {
                    *defaultCacheIndex = i;  // remember for caller
                }
                    
                [item setAttributedTitle: title];
                [item setState: itemState];
                [item setEnabled: YES];
            } else {
                [item setTitle: @"error"];  // This should never happen
                [item setEnabled: NO];
            }
        }
    }
}

// ---------------------------------------------------------------------------

+ (NSString *) stringForErrorCode: (KLStatus) error
{
    NSString *string = NULL;
    char *errorText;
    
    if (KLGetErrorString (error, &errorText) == klNoErr) { 
        string = [NSString stringWithUTF8String: errorText]; 
        KLDisposeString (errorText);
    } else {
        string = [NSString stringWithFormat: NSLocalizedString (@"KAppStringUnknownErrorFormat", NULL), error];
    }
    
    return string;
}

// ---------------------------------------------------------------------------

+ (void) displayAlertForError: (KLStatus) error 
                       action: (int) action 
                       sender: (id) sender
{
    NSWindow *parentWindow = NULL;
    if ([sender isMemberOfClass: [NSWindowController class]]) { parentWindow = [sender window]; }
    if ([sender isMemberOfClass: [NSWindow class]])           { parentWindow = sender; }
    
    NSString *key = @"KAppStringGenericError";
    
    switch (action) {
        case kGetTicketsAction:
            key = @"KAppStringGetTicketsError";
            break;
        case kRenewTicketsAction:
            key = @"KAppStringRenewTicketsError";
            break;
        case kDestroyTicketsAction:
            key = @"KAppStringDestroyTicketsError";
            break;
        case kChangePasswordAction:
            key = @"KAppStringChangePasswordError";
            break;
        case kChangeActiveUserAction:
            key = @"KAppStringChangeActiveUserError";
            break;
    }
        
    NSAlert *alert = [[[NSAlert alloc] init] autorelease];
    [alert addButtonWithTitle: NSLocalizedString (@"KAppStringOK", NULL)];
    [alert setMessageText: NSLocalizedString (key, NULL)];
    [alert setInformativeText: [Utilities stringForErrorCode: error]];
    [alert setAlertStyle: NSWarningAlertStyle];
    
    
    if (parentWindow != NULL) {
        [alert beginSheetModalForWindow: parentWindow 
                          modalDelegate: sender 
                         didEndSelector: @selector(errorSheetDidEnd:returnCode:contextInfo:) 
                            contextInfo: NULL];
    } else {
        [alert runModal];
    }
}

@end
