//
//  CyTVServer.m
//  CyTV Server
//
//  Created by Andreas Junghans on Thu Aug 21 2003.
//  Copyright (c) 2003-2004 Andreas Junghans. All rights reserved.
//

#import "CyTVServer.h"
#import "URLFetcher.h"
#import "Util.h"


/**
 * Singleton for getting the contents of URLs.
 */

static URLFetcher* _urlFetcher = nil;


/**
 * Implementation of the interface available to the AppleScript parts.
 */

@implementation NSApplication (CyTVServerInterface)

- (NSString*) getEyeTVArchivePath {
    // returns EyeTV's archive directory
    
    NSString* retVal = @"";
    
    // first, read the archive folder data from the preferences
    NSString* prefsPath = [@"~/Library/Preferences/com.elgato.eyetv.plist" stringByExpandingTildeInPath];
    //printf("%s\n", [prefsPath cString]);
    NSData* prefsData = [NSData dataWithContentsOfFile: prefsPath];
    if (prefsData == nil) {
        return retVal;
    }
    NSString* error;
    NSPropertyListFormat format;
    id prefs = [NSPropertyListSerialization propertyListFromData: prefsData
                                            mutabilityOption: NSPropertyListImmutable
                                            format: &format
                                            errorDescription: &error];
    if (!prefs) {
        [error release];
        return retVal;
    }
    NSData* archiveFolderData = [prefs objectForKey: @"archive folder"];
    if (!archiveFolderData) {
        return retVal;
    }
    
    // now convert the data to an alias handle and resolve the alias
    Handle handle = NewHandle([archiveFolderData length]);
    if (!handle) {
        return retVal;
    }
    HLock(handle);
    BlockMoveData([archiveFolderData bytes], *handle, [archiveFolderData length]);
    HUnlock(handle);
    FSRef archiveFolderRef;
    Boolean wasChanged;
    OSErr result = FSResolveAlias(NULL, (AliasHandle) handle, &archiveFolderRef, &wasChanged);
    DisposeHandle(handle);
    if (result != noErr) {
        return retVal;
    }

    // finally, get the path in UTF-8 format
    size_t bufferSize = 1000;
    UInt8* pathBytes = malloc(bufferSize);
    OSStatus status;
    do {
        status = FSRefMakePath(&archiveFolderRef, pathBytes, bufferSize);
        if (status == pathTooLongErr) {
            free(pathBytes);
            bufferSize <<= 1;
            pathBytes = malloc(bufferSize);
        }
    } while (status == pathTooLongErr);
    if (status == noErr) {
        retVal = [NSString stringWithUTF8String: pathBytes];
    }
    free(pathBytes);

    return retVal;
}

- (NSString *) getURL: (NSString*) url {
    if (_urlFetcher == nil) {
        _urlFetcher = [[URLFetcher alloc] init];
    }
    return [_urlFetcher fetchURL:url];
}

- (NSString*) encodeURL: (NSString*) string {
    // encode a string by converting it to UTF-8, then
    // express every non-alphanumeric character in hex notation
    // usable for URLs (e.g. "%2f")
    
    const char* utf8String = [string UTF8String];
    size_t utf8len = strlen(utf8String);
    if (utf8len == 0) {
        return @"";
    }
    int i;
    char* result = malloc(utf8len*3+1);
    char* ptr = result;
    int code;
    for (i = 0; i < utf8len; ++i) {
        code = ((int) utf8String[i]) & 0xff;
        if ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z') ||
            (code >= '0' && code <= '9')) {
            *ptr++ = code;
        } else {
            sprintf(ptr, "%%%.2x", ((int) utf8String[i]) & 0xff);
            ptr += 3;
        }
    }
    *ptr = 0;
    
    NSString* retVal = [NSString stringWithCString: result];
    free(result);
    return retVal;
}

- (NSString *) loadPreference: (NSString*) key {
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    NSString* retVal = [defaults stringForKey: key];
    if (retVal == nil) {
        return @"";
    }
    return retVal;
}

- (void) savePreference: (NSString*) key value: (NSString*) value {
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject: value forKey: key];
    [defaults synchronize];
}

- (int)findPortStartingWith:(int)startPort {
    return [Util findPortStartingWith:startPort];
}

- (int)findPortStartingWith:(int)startPort excluding:(int)excludedPort {
    return [Util findPortStartingWith:startPort excluding:excludedPort];
}

- (NSString*)getCyTVLogPath {
    return [Util getCyTVLogPath];
}

- (NSString*)getCyTVSupportPath {
    return [Util getCyTVSupportPath];
}

@end
