//
//  UITextStyleSettings.m
//  iFileReader
//
//  Created by LiDong on 13-4-11.
//  Copyright (c) 2013年 LiDong. All rights reserved.
//

#import "UITextStyleSettings.h"
#import "UISettings.h"
#import "FSFileItem.h"

@implementation UITextStyleSettings

@synthesize encoding = _encoding;
@synthesize fontSize = _fontSize;
@synthesize fontName = _fontName;
@synthesize fontDisplayName = _fontDisplayName;
@synthesize filePath = _filePath;

#define kTextEncodingKey @"com.apple.TextEncoding"
#define kFontNameKey @"com.kingfont.FontName"
#define kFontSizeKey @"com.kingfont.FontSize"

- (id)initWithPath:(NSString *)path {
    if (self = [super init]) {
        _filePath = path;
        
        NSDictionary *attributes = [theFileManager attributesOfItemAtPath:_filePath error:NULL];
        NSDictionary *extendedAttributes = [attributes valueForKey:NSFileExtendedAttributes];
        NSData *encodingData = [extendedAttributes valueForKey:kTextEncodingKey];
        NSString *encodingString = [[NSString alloc] initWithData:encodingData encoding:NSUTF8StringEncoding];
        NSArray *components = [encodingString componentsSeparatedByString:@";"];
        NSData *fontData = [extendedAttributes valueForKey:kFontNameKey];
        NSData *sizeData = [extendedAttributes valueForKey:kFontSizeKey];
        
        if ([components count] > 1) {
            _encoding = (CFStringEncoding)[[components objectAtIndex:1] intValue];
            if (!CFStringIsEncodingAvailable(_encoding)) {
                _encoding = UISettingsGetCFStringEncoding();
            }
        } else {
            _encoding = UISettingsGetCFStringEncoding();
        }
        if ([fontData length] > 0) {
            NSString *fontName = [[NSString alloc] initWithData:fontData encoding:NSUTF8StringEncoding];
            
            [self setFontName:fontName];
        } else {
            [self setFontName:UISettingsGetFontName()];
        }
        if ([sizeData length] > 0) {
            NSString *sizeValue = [[NSString alloc] initWithData:sizeData encoding:NSUTF8StringEncoding];
            
            _fontSize = (UInt32)[sizeValue intValue];
        } else {
            _fontSize = UISettingsGetFontSize();
        }
    }
    return self;
}

- (id)init {
    if (self = [super init]) {
        _encoding = UISettingsGetCFStringEncoding();
        _fontSize = UISettingsGetFontSize();
        [self setFontName:UISettingsGetFontName()];
    }
    return self;
}

- (void)setFontName:(NSString *)fontName {
    if (fontName != _fontName) {
        _fontName = fontName;
        _fontDisplayName = UISettingsGetDisplayNameForFontNamed(_fontName);
    }
}

- (NSDictionary *)fileAttributes {
    if (_filePath) {
        NSString *encodingString = [[NSString alloc] initWithFormat:@"%@;%lu", UISettingsGetEncodingNameForCFStringEncoding(_encoding), _encoding];
        NSString *fontSizeString = [[NSString alloc] initWithFormat:@"%lu", _fontSize];
        NSDictionary *extendedAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[encodingString dataUsingEncoding:NSUTF8StringEncoding], kTextEncodingKey, [_fontName dataUsingEncoding:NSUTF8StringEncoding], kFontNameKey, [fontSizeString dataUsingEncoding:NSUTF8StringEncoding], kFontSizeKey, nil];
        NSDictionary *oldAttributes = [theFileManager attributesOfItemAtPath:_filePath error:NULL];
        NSMutableDictionary *newAttributes = [[NSMutableDictionary alloc] initWithDictionary:oldAttributes];
        
        [newAttributes setValue:extendedAttributes forKey:NSFileExtendedAttributes];
        return newAttributes;
    }
    return nil;
}

- (void)save {
    if (_filePath) {
        [theFileManager setAttributes:[self fileAttributes] ofItemAtPath:_filePath error:NULL];
    } else {
        UISettingsSetCFStringEncoding(_encoding);
        UISettingsSetFontName(_fontName);
        UISettingsSetFontSize(_fontSize);
    }
}

- (UIFont *)font {
    return [UIFont fontWithName:_fontName size:_fontSize];
}

- (UIFont *)fontForSubTitle {
    const CGFloat size = [_fontName isEqualToString:@"Zapfino"] ? 10 : 14;
    
    return [UIFont fontWithName:_fontName size:size];
}

- (void)dealloc {
}

@end

static const CFStringEncoding __encodings[kNumberOfEncodings] = {
    kCFStringEncodingMacRoman,
    kCFStringEncodingWindowsLatin1,
    kCFStringEncodingISOLatin1,
    kCFStringEncodingNextStepLatin,
    kCFStringEncodingASCII,
    kCFStringEncodingUnicode,
    kCFStringEncodingUTF8,
    kCFStringEncodingNonLossyASCII,
    kCFStringEncodingUTF16,
    kCFStringEncodingUTF16BE,
    kCFStringEncodingUTF16LE,
    kCFStringEncodingUTF32,
    kCFStringEncodingUTF32BE,
    kCFStringEncodingUTF32LE,
    kCFStringEncodingMacJapanese,
    kCFStringEncodingMacChineseTrad,
    kCFStringEncodingMacKorean,
    kCFStringEncodingMacArabic,
    kCFStringEncodingMacHebrew,
    kCFStringEncodingMacGreek,
    kCFStringEncodingMacCyrillic,
    kCFStringEncodingMacUkrainian,
    kCFStringEncodingISOLatin2,
    kCFStringEncodingISOLatin3,
    kCFStringEncodingISOLatin4,
    kCFStringEncodingISOLatinCyrillic,
    kCFStringEncodingISOLatinArabic,
    kCFStringEncodingISOLatinGreek,
    kCFStringEncodingISOLatinHebrew,
    kCFStringEncodingISOLatin5,
    kCFStringEncodingISOLatin6,
    kCFStringEncodingISOLatinThai,
    kCFStringEncodingISOLatin7,
    kCFStringEncodingISOLatin8,
    kCFStringEncodingISOLatin9,
    kCFStringEncodingISOLatin10,
    kCFStringEncodingDOSLatinUS,
    kCFStringEncodingDOSGreek,
    kCFStringEncodingDOSBalticRim,
    kCFStringEncodingDOSLatin1,
    kCFStringEncodingDOSGreek1,
    kCFStringEncodingDOSLatin2,
    kCFStringEncodingDOSCyrillic,
    kCFStringEncodingDOSTurkish,
    kCFStringEncodingDOSPortuguese,
    kCFStringEncodingDOSIcelandic,
    kCFStringEncodingDOSHebrew,
    kCFStringEncodingDOSCanadianFrench,
    kCFStringEncodingDOSArabic,
    kCFStringEncodingDOSNordic,
    kCFStringEncodingDOSRussian,
    kCFStringEncodingDOSGreek2,
    kCFStringEncodingDOSThai,
    kCFStringEncodingDOSJapanese,
    kCFStringEncodingDOSChineseSimplif,
    kCFStringEncodingDOSKorean,
    kCFStringEncodingDOSChineseTrad,
    kCFStringEncodingWindowsLatin2,
    kCFStringEncodingWindowsCyrillic,
    kCFStringEncodingWindowsGreek,
    kCFStringEncodingWindowsLatin5,
    kCFStringEncodingWindowsHebrew,
    kCFStringEncodingWindowsArabic,
    kCFStringEncodingWindowsBalticRim,
    kCFStringEncodingWindowsVietnamese,
    kCFStringEncodingGB_18030_2000,
    kCFStringEncodingISO_2022_JP,
    kCFStringEncodingISO_2022_JP_2,
    kCFStringEncodingISO_2022_JP_1,
    kCFStringEncodingISO_2022_CN,
    kCFStringEncodingISO_2022_CN_EXT,
    kCFStringEncodingISO_2022_KR,
    kCFStringEncodingEUC_JP,
    kCFStringEncodingEUC_CN,
    kCFStringEncodingEUC_TW,
    kCFStringEncodingEUC_KR,
    kCFStringEncodingShiftJIS,
    kCFStringEncodingKOI8_R,
    kCFStringEncodingBig5,
    kCFStringEncodingMacRomanLatin1,
    kCFStringEncodingHZ_GB_2312,
    kCFStringEncodingBig5_HKSCS_1999,
    kCFStringEncodingKOI8_U,
    kCFStringEncodingEBCDIC_CP037,
    kCFStringEncodingUTF7,
    kCFStringEncodingUTF7_IMAP
};

static const char *__encodingNames[kNumberOfEncodings] = {
    "MacRoman",
    "WindowsLatin1",
    "ISOLatin1",
    "NextStepLatin",
    "ASCII",
    "Unicode",
    "UTF8",
    "NonLossyASCII",
    "UTF16",
    "UTF16BE",
    "UTF16LE",
    "UTF32",
    "UTF32BE",
    "UTF32LE",
    "MacJapanese",
    "MacChineseTrad",
    "MacKorean",
    "MacArabic",
    "MacHebrew",
    "MacGreek",
    "MacCyrillic",
    "MacUkrainian",
    "ISOLatin2",
    "ISOLatin3",
    "ISOLatin4",
    "ISOLatinCyrillic",
    "ISOLatinArabic",
    "ISOLatinGreek",
    "ISOLatinHebrew",
    "ISOLatin5",
    "ISOLatin6",
    "ISOLatinThai",
    "ISOLatin7",
    "ISOLatin8",
    "ISOLatin9",
    "ISOLatin10",
    "DOSLatinUS",
    "DOSGreek",
    "DOSBalticRim",
    "DOSLatin1",
    "DOSGreek1",
    "DOSLatin2",
    "DOSCyrillic",
    "DOSTurkish",
    "DOSPortuguese",
    "DOSIcelandic",
    "DOSHebrew",
    "DOSCanadianFrench",
    "DOSArabic",
    "DOSNordic",
    "DOSRussian",
    "DOSGreek2",
    "DOSThai",
    "DOSJapanese",
    "DOSChineseSimplif",
    "DOSKorean",
    "DOSChineseTrad",
    "WindowsLatin2",
    "WindowsCyrillic",
    "WindowsGreek",
    "WindowsLatin5",
    "WindowsHebrew",
    "WindowsArabic",
    "WindowsBalticRim",
    "WindowsVietnamese",
    "GB_18030_2000",
    "ISO_2022_JP",
    "ISO_2022_JP_2",
    "ISO_2022_JP_1",
    "ISO_2022_CN",
    "ISO_2022_CN_EXT",
    "ISO_2022_KR",
    "EUC_JP",
    "EUC_CN",
    "EUC_TW",
    "EUC_KR",
    "ShiftJIS",
    "KOI8_R",
    "Big5",
    "MacRomanLatin1",
    "HZ_GB_2312",
    "Big5_HKSCS_1999",
    "KOI8_U",
    "EBCDIC_CP037",
    "UTF7",
    "UTF7_IMAP"
};

CFStringEncoding UISettingsGetCFStringEncodingForIndex(const UInt8 index) {
    return (kNumberOfEncodings <= index) ? kCFStringEncodingUTF8 : __encodings[index];
}

NSStringEncoding UISettingsGetNSStringEncodingForIndex(const UInt8 index) {
    const CFStringEncoding encoding = (kNumberOfEncodings <= index) ? kCFStringEncodingUTF8 : __encodings[index];
    
    return CFStringConvertEncodingToNSStringEncoding(encoding);
}

UInt8 UISettingsGetIndexForEncoding(const CFStringEncoding encoding) {
    for (UInt8 i = 0; i < kNumberOfEncodings; ++ i) {
        if (encoding == __encodings[i]) {
            return i;
        }
    }
    return (UInt8)-1;
}

NSStringEncoding UISettingsGetCFStringEncoding() {
    return __encodings[UISettingsGetEncodingIndex()];
}

NSStringEncoding UISettingsGetNSStringEncoding() {
    return CFStringConvertEncodingToNSStringEncoding(__encodings[UISettingsGetEncodingIndex()]);
}

void UISettingsSetCFStringEncoding(const CFStringEncoding encoding) {
    for (UInt8 i = 0; i < kNumberOfEncodings; ++ i) {
        if (encoding == __encodings[i]) {
            UISettingsSetEncodingIndex(i);
            return;
        }
    }
    UISettingsSetEncodingIndex(6);
}

NSString *UISettingsGetEncodingNameForIndex(const UInt8 index) {
    const char *cName = (kNumberOfEncodings <= index) ? __encodingNames[6] : __encodingNames[index];
    NSString *encodingName = [[NSString alloc] initWithBytes:cName length:strlen(cName) encoding:NSUTF8StringEncoding];
    
    return encodingName;
}

NSString *UISettingsGetEncodingNameForCFStringEncoding(const CFStringEncoding encoding) {
    const UInt8 index = UISettingsGetIndexForEncoding(encoding);
    
    return UISettingsGetEncodingNameForIndex(index);
}

NSString *UISettingsGetEncodingName(void) {
    const char *cName = __encodingNames[UISettingsGetEncodingIndex()];
    NSString *encodingName = [[NSString alloc] initWithBytes:cName length:strlen(cName) encoding:NSUTF8StringEncoding];
    
    return encodingName;
}

NSArray *UISettingsGetAllEncodingNames(void) {
    NSMutableArray *allNames = [[NSMutableArray alloc] initWithCapacity:kNumberOfEncodings];
    
    for (NSInteger i = 0; i < kNumberOfEncodings; ++ i) {
        const char *cName = __encodingNames[i];
        NSString *encodingName = [[NSString alloc] initWithBytes:cName length:strlen(cName) encoding:NSUTF8StringEncoding];
        
        [allNames addObject:encodingName];
    }
    return allNames;
}

