//
//  TeXDistributionUtils.m
//  TeXDist
//
//  Created by coder on 08/12/06.
//  Copyright 2006 Laurens'Tribune. All rights reserved.
//

#import "TeXDistCommon.h"
#import "TeXDistributionUtils.h"
#import <sys/sysctl.h>
#import <sys/stat.h>

@implementation NSURL(TeXDistUtils)
- (NSString *) programsPath4TeXDist;
{
    return [self.path stringByAppendingPathComponent:[TeXDistUtils programsRelativePath]];
}
@end

@implementation TeXDistUtils
+ (NSBundle *)bundle;
{
	return [NSBundle bundleForClass:[TeXDistUtils class]];
}
+ (NSDictionary *)defaults;
{
	static NSDictionary * defaults = nil;
	if (NOT defaults) {
		NSBundle * B = self.bundle;
		NSString * path = [B pathForResource:@"setup" ofType:@"plist"];
        TeXDistLog(2,@"TeXDist INFO: defaults at %@",path);
		if (path) {
			NSURL * url = [NSURL fileURLWithPath:path];
			defaults = [[NSDictionary dictionaryWithContentsOfURL:url] retain];
		} else {
            TeXDistLog(TeXDistLogLevelAlways,@"! TeXDist INFO: NO SETUP");
			defaults = [[NSDictionary dictionary] retain];
		}
	}
	return defaults;
}
+ (NSString *)texdistExtension;
{
	NSString * extension = [[self defaults] objectForKey:TeXDistExtensionKey];
	if (NOT [extension isKindOfClass:[NSString class]]) {
		extension = TeXDistExtensionKey;
	}
	return extension;
}
+ (NSArray *) expectedPrograms;
{
	static NSArray * expectedPrograms = nil;
	if(NOT expectedPrograms)
	{
		expectedPrograms = [[self defaults] objectForKey:TeXDistSetUpExpectedProgramsKey];
		if(NOT [expectedPrograms isKindOfClass:[NSArray class]])
		{
			expectedPrograms = [NSArray array];
		}
	}
	return expectedPrograms;
}
#import <mach/machine.h>
+ (cpu_type_t) CPUType;
{
	cpu_type_t cpu_type;
	size_t length = sizeof(cpu_type);
    int value = 0;
    sysctlbyname("hw.cputype", &cpu_type, &length, NULL, 0);
    length = sizeof(value);
    switch (cpu_type&~CPU_ARCH_MASK) {
        case CPU_TYPE_X86:
            if (!sysctlbyname("hw.cpu64bit_capable", &value, &length, NULL, 0)) {
                cpu_type |= CPU_ARCH_ABI64;
            }
            break;
        case CPU_TYPE_POWERPC:
             if (NOT sysctlbyname("hw.optional.64bitops", &value, &length, NULL, 0)) {
                cpu_type |= CPU_ARCH_ABI64;
            }
            break;
        default:
            TeXDistLog(-1,@"TeXDist ERROR: unknown CPU type %ul",(unsigned long)cpu_type);
            break;
    }
    return cpu_type;
}
+ (NSString *) archForCPU:(cpu_type_t)CPUType;
{
    switch (CPUType) {
#define SWITCH_CASE(ID) case CPU_TYPE_##ID:return [[NSString stringWithFormat:@"%s",#ID] lowercaseString]
#if 0
        SWITCH_CASE(VAX);
		SWITCH_CASE(MC680x0);
		SWITCH_CASE(MC98000);
		SWITCH_CASE(HPPA);
		SWITCH_CASE(MC88000);
		SWITCH_CASE(SPARC);
		SWITCH_CASE(I860);
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
		SWITCH_CASE(X86_64);
		case CPU_TYPE_POWERPC64:return @"ppc64";
#endif
		SWITCH_CASE(I386);
		case CPU_TYPE_POWERPC:return @"ppc";
		default: return @"default";
    }
}
+ (cpu_type_t) CPUForArch:(NSString *)arch;
{
    if ([arch isEqual:@"ppc"]) {
        return CPU_TYPE_POWERPC;
    }
    if ([arch isEqual:@"ppc64"]) {
        return CPU_TYPE_POWERPC64;
    }
    if ([arch isEqual:@"i386"] OR [arch isEqual:@"x86"]) {
        return CPU_TYPE_X86;
    }
    if ([arch isEqual:@"x86_64"]) {
        return CPU_TYPE_X86_64;
    }
    return CPU_TYPE_ANY;
}
+ (NSArray *) namesOfCPU:(cpu_type_t)CPUType;
{
	static NSDictionary * CPUNamesPriorityByArch = nil;
	if (!CPUNamesPriorityByArch) {
		CPUNamesPriorityByArch = [[self defaults] objectForKey:TeXDistSetUpCPUNamesPriorityByArchKey];
		if (![CPUNamesPriorityByArch isKindOfClass:[NSDictionary class]]) {
			CPUNamesPriorityByArch = [NSDictionary dictionary];
		}
	}
	NSString * arch = [self archForCPU:CPUType];
	id result = [CPUNamesPriorityByArch objectForKey:arch];
	return [result isKindOfClass:[NSArray class]]? result:
		([result isKindOfClass:[NSString class]]?
			[NSArray arrayWithObject:result]:
			[NSArray array]);
}
+ (NSArray *) CPUNames;
{
	return [self namesOfCPU:[self CPUType]];
}
+ (BOOL)isAlternateKeyDown;
{
    return kCGEventFlagMaskAlternate & CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState);
}
+ (NSString *)contentsRelativePath;
{
	return [[self programsRelativePath] stringByDeletingLastPathComponent];
}
+ (NSString *)programsRelativePath;
{
	NSString * path = [[self defaults] objectForKey:TeXDistSetUpProgramsRelativeKey];
	if(NOT [path isKindOfClass:[NSString class]])
	{
		path = TeXDistSetUpProgramsRelativeKey;
	}
	return path;
}
+ (NSString *)texbinRelativePath;
{
	return [[self programsRelativePath] stringByAppendingPathComponent:TeXDist_texbin];
}
+ (NSString *)defaultProgramsPath;
{
	return [[TeXDistUtils activeDistributionPath] stringByAppendingPathComponent:
		[TeXDistUtils programsRelativePath]];
}
+ (NSString *)rootRelativePath;
{
	NSString * path = [[self defaults] objectForKey:TeXDistSetUpRootRelativeKey];
	if(NOT [path isKindOfClass:[NSString class]])
	{
		path = TeXDistSetUpRootRelativeKey;
	}
	return path;
}
+ (NSURL *)distributionsURL;
{
	NSString * LibraryTeX = [[self defaults] objectForKey:TeXDistSetUpLibraryTeXKey];
	if (NOT [LibraryTeX isKindOfClass:[NSString class]]) {
		LibraryTeX = TeXDistSetUpLibraryTeXKey;
	}
	return [NSURL fileURLWithPath:LibraryTeX];
}
+ (NSString *)activeDistributionPath;
{
	NSString * defaultTeX = [[self defaults] objectForKey:TeXDistSetUpDefaultTeXKey];
	if (NOT [defaultTeX isKindOfClass:[NSString class]]) {
		defaultTeX = TeXDistSetUpDefaultTeXKey;
	}
	return defaultTeX;
}
+ (NSString *)activeDistributionContentsPath;
{
	return [[self activeDistributionProgramsPath] stringByDeletingLastPathComponent];
}
+ (NSString *)activeDistributionProgramsPath;
{
	return [[self activeDistributionPath] stringByAppendingPathComponent:[TeXDistUtils programsRelativePath]];
}
+ (NSString *)activeDistributionProgramsPath_texbin;
{
	return [[self activeDistributionPath] stringByAppendingPathComponent:[TeXDistUtils texbinRelativePath]];
}
+ (NSString *) path_texbin;
{
	NSString * path = [[self defaults] objectForKey:TeXDistSetUp_usr_texbin_Key];
	if(NOT [path isKindOfClass:[NSString class]])
	{
		path = TeXDistSetUp_usr_texbin_Key;
	}
	return path;
}
#define TeXDist_isExecutableFileAtPath(THE_PATH)\
	(([[[NSFileManager defaultManager] attributesOfItemAtPath:[THE_PATH stringByResolvingSymlinksInPath] error:NULL] filePosixPermissions]&(S_IXUSR|S_IXGRP|S_IXOTH))\
		==(S_IXUSR|S_IXGRP|S_IXOTH))
+ (NSDictionary *)minimumSystemVersionsByArch;
{
    NSDictionary * D = [[self defaults] objectForKey:TeXDistSetUpMinimumSystemVersionsByArchKey];
    NSMutableDictionary * MD = [NSMutableDictionary dictionary];
    for (NSString * arch in D.allKeys) {
        TeXDistSystemVersion *TDSV = [TeXDistSystemVersion systemVersionWithString:[D objectForKey:arch] error:NULL];
        [MD setObject:(TDSV?:[TeXDistSystemVersion firstSystemVersion]) forKey:arch];
    }
    return [MD.copy autorelease];
}
+ (NSDictionary *)maximumSystemVersionsByArch;
{
    NSDictionary * D = [[self defaults] objectForKey:TeXDistSetUpMaximumSystemVersionsByArchKey];
    NSMutableDictionary * MD = [NSMutableDictionary dictionary];
    for (NSString * arch in D.allKeys) {
        TeXDistSystemVersion *TDSV = [TeXDistSystemVersion systemVersionWithString:[D objectForKey:arch] error:NULL];
        [MD setObject:(TDSV?:[TeXDistSystemVersion lastSystemVersion]) forKey:arch];
    }
    return [MD.copy autorelease];
}
+ (NSDictionary *)architecturePriorityByArch;
{
    return [[self defaults] objectForKey:TeXDistSetUpArchitecturePrioritiesByArchKey];
}
@end

