//
//  UISettings.m
//  Downloader
//
//  Created by hxhg-LiDong on 13-1-30.
//  Copyright (c) 2013年 LiDong. All rights reserved.
//

#import "UISettings.h"

#define UISettingsMagic 0x4B696E67666F6E74ULL
#define FONT_NAME_MAX 64
#define UISettingsFileName @"__settings__.config"
#define UISettingsFilePath [FSLibraryDirectory stringByAppendingPathComponent:UISettingsFileName]

typedef struct __UISettingsHeader {
    UInt64 magic;
    UInt32 version;
    UInt32 size;
} UISettingsHeader;

typedef struct __UISettings {
    UISettingsHeader header;
    
    // general
    UInt8 orientation_locked;
    UInt8 general_reserved[63];
    
    // file system
    UInt8 fs_show_extensions;
    UInt8 fs_sorting_mode;
    UInt8 fs_sorting_descending;
    UInt8 fs_reserved[61];
    
    // text viewer
    UInt8 txt_encoding_index;
    UInt8 txt_font_size;
    UInt8 txt_reserved[58];
    
    // pdf viewer
    UInt8 pdf_reserved[64];
    
    // image viewer
    UInt8 img_reserved[64];
    
    // global reserved
    UInt8 global_reserved[7856];
    
    // string
    char web_home_page[PATH_MAX];
    char txt_font_name[FONT_NAME_MAX];
} UISettings;

static UISettings __settings;


#pragma mark - Intialiaze / Finalize
////////////////////////////////////////////////////////////////////////////////
// intitialize / finalize

void UISettingsInitialize(void) {
    NSString *path = UISettingsFilePath;
    const int fd = open([path fileSystemRepresentation], O_RDONLY);
    
    if (-1 < fd) {
        int bytes = read(fd, &__settings, sizeof(UISettings));
        
        if (sizeof(UISettings) <= bytes && UISettingsMagic == __settings.header.magic && sizeof(UISettings) <= __settings.header.size) {
        } else {
            memset(&__settings, 0, sizeof(UISettings));
        }
        close(fd);
    }
}

void UISettingsSynchronize(void) {
    NSString *path = UISettingsFilePath;
    BOOL isDirectory = NO;
    
    if (![theFileManager fileExistsAtPath:path isDirectory:&isDirectory] || isDirectory) {
        if (isDirectory) {
            [theFileManager removeItemAtPath:path error:NULL];
        }
        [theFileManager createFileAtPath:path contents:nil attributes:nil];
    }
    const int fd = open([path fileSystemRepresentation], O_WRONLY);
    
    if (-1 < fd) {
        __settings.header.magic = UISettingsMagic;
        __settings.header.size = sizeof(UISettings);
        __settings.header.version = 0;
        
        const char *begin = (const char *)&__settings;
        const char *end = begin + sizeof(UISettings);
        int bytes = 0;
        
        for (const char *cursor = begin; cursor < end; cursor += bytes) {
            bytes = write(fd, cursor, (end - cursor));
            
            if (0 >= bytes) {
                break;
            }
        }
        
        close(fd);
    }
}

void UISettingsFinalize(void) {
    UISettingsSynchronize();
}


#pragma mark - Orientation
////////////////////////////////////////////////////////////////////////////////
// orientation

void UISettingsLockOrientation(const BOOL flag) {
    __settings.orientation_locked = flag;
}

BOOL UISettingsOrientationIsLocked(void) {
    return __settings.orientation_locked;
}

BOOL UISettingsOrientationInvertLocked(void) {
    __settings.orientation_locked = !__settings.orientation_locked;
    return __settings.orientation_locked;
}

BOOL UISettingsShouldRotateToInterfaceOrientation(UIInterfaceOrientation interfaceOrientation) {
    if (__settings.orientation_locked) {
        return ([theApplication statusBarOrientation] == interfaceOrientation);
    }
    return YES;
}

UIInterfaceOrientationMask UISettingsSupportedInterfaceOrientation(void) {
    if (__settings.orientation_locked) {
        return (1 << [theApplication statusBarOrientation]);
    }
    return UIInterfaceOrientationMaskAll;
}


#pragma mark - File Extensions
////////////////////////////////////////////////////////////////////////////////
// file extension

BOOL UISettingsShowFileExtensions(void) {
    return __settings.fs_show_extensions;
}

void UISettingsSetShowFileExtensions(const BOOL flag) {
    __settings.fs_show_extensions = flag;
}

BOOL UISettingsInvertShowFileExtensions(void) {
    __settings.fs_show_extensions = !__settings.fs_show_extensions;
    return __settings.fs_show_extensions;
}


#pragma mark - File Sorting
////////////////////////////////////////////////////////////////////////////////
// file sorting

FSSortingMode UISettingsGetSortingMode(void) {
    return __settings.fs_sorting_mode;
}

void UISettingsSetSortingMode(const FSSortingMode mode) {
    __settings.fs_sorting_mode = mode;
}

FSSortingOrder UISettingsGetSortingOrder(void) {
    return (__settings.fs_sorting_descending ? NSOrderedDescending : NSOrderedAscending);
}

void UISettingsSetSortingOrder(const FSSortingOrder order) {
    __settings.fs_sorting_descending = (NSOrderedDescending == order) ? YES : NO;
}

void UISettingsSetSortingData(const FSSortingMode mode, const FSSortingOrder order) {
    __settings.fs_sorting_mode = mode;
    __settings.fs_sorting_descending = (NSOrderedDescending == order) ? YES : NO;
}

#pragma mark - Text Encoding
////////////////////////////////////////////////////////////////////////////////
// text encoding

UInt8 UISettingsGetEncodingIndex(void) {
    const UInt8 index = __settings.txt_encoding_index + 6;
    
    if (kNumberOfEncodings <= index) {
        __settings.txt_encoding_index = 0;
        return 6;
    }
    return index;
}

void UISettingsSetEncodingIndex(const UInt8 index) {
    __settings.txt_encoding_index = index - (UInt8)6;
}

#pragma mark - Text Font
////////////////////////////////////////////////////////////////////////////////
// text font

NSString *UISettingsGetFontName(void) {
    const int len = strnlen(__settings.txt_font_name, FONT_NAME_MAX);
    
    if (0 < len) {
        NSString *name = [[NSString alloc] initWithBytesNoCopy:__settings.txt_font_name length:len encoding:NSUTF8StringEncoding freeWhenDone:NO];
        
        return name;
    }
    
    return @"HelveticaNeue";
}

NSString *UISettingsGetDisplayNameForFontNamed(NSString *fontName) {
    const char *cFontName = [fontName UTF8String];
    const NSInteger len = strnlen(cFontName, FONT_NAME_MAX);
    
    if (0 < len) {
        char new_name[FONT_NAME_MAX * 2];
        BOOL canFillBlank = NO;
        int j = 0;
        
        for (int i = 0; i < len; ++ i) {
            char c = cFontName[i];
            
            if (isupper(c)) {
                if (canFillBlank) {
                    new_name[j ++] = '\x20';
                    canFillBlank = NO;
                }
            } else {
                canFillBlank = YES;
                if ('-' == c) {
                    c = '\x20';
                }
            }
            new_name[j ++] = c;
        }
        
        NSString *displayName = [[NSString alloc] initWithBytes:new_name length:j encoding:NSUTF8StringEncoding];
        
        return displayName;
    }
    
    return @"Helvetica Neue";
}

NSString *UISettingsGetFontDisplayName(void) {
    NSString *fontName = UISettingsGetFontName();
    
    return UISettingsGetDisplayNameForFontNamed(fontName);
}

UIFont *UISettingsGetFont(void) {
    return [UIFont fontWithName:UISettingsGetFontName() size:(UInt8)(__settings.txt_font_size + (UInt8)14)];
}

UIFont *UISettingsGetFontForSubTitle(void) {
    NSString *fontName = UISettingsGetFontName();
    const CGFloat size = [fontName isEqualToString:@"Zapfino"] ? 10 : 14;
    
    return [UIFont fontWithName:fontName size:size];
}

void UISettingsSetFontName(NSString *fontName) {
    const char *cString = [fontName UTF8String];
    
    if (cString) {
        const int len = strnlen(cString, FONT_NAME_MAX);
        
        memcpy(__settings.txt_font_name, cString, len);
        if (FONT_NAME_MAX > len) {
            __settings.txt_font_name[len] = '\0';
        }
    } else {
        memset(__settings.txt_font_name, 0, FONT_NAME_MAX);
    }
}

UInt8 UISettingsGetFontSize(void) {
    return (__settings.txt_font_size + (UInt8)14);
}

void UISettingsSetFontSize(const UInt8 size) {
    __settings.txt_font_size = size - (UInt8)14;
}


#pragma mark - Web Browser
////////////////////////////////////////////////////////////////////////////////
// web browser

NSString *UISettingsGetHomePage(void) {
    const int len = strnlen(__settings.web_home_page, PATH_MAX);
    
    if (0 < len) {
        NSString *URLString = [[NSString alloc] initWithBytesNoCopy:__settings.web_home_page length:len encoding:NSUTF8StringEncoding freeWhenDone:NO];
        
        return URLString;
    }
    return @"http://www.google.com";
}

void UISettingsSetHomePage(NSString *URLString) {
    const char *cString = [URLString UTF8String];
    
    if (cString) {
        const int len = strnlen(cString, PATH_MAX);
        
        memcpy(__settings.web_home_page, cString, len);
        if (PATH_MAX > len) {
            __settings.web_home_page[len] = '\0';
        }
    } else {
        memset(__settings.web_home_page, 0, PATH_MAX);
    }
}

