//
//  LFFolder.m
//  Localize Folder
//
//  Created by Kim Wittenburg on 05.07.13.
//  Copyright (c) 2013 Kim Wittenburg. All rights reserved.
//

#import "LFFolder.h"

#import <Foundation/FoundationErrors.h>

NSString *const LFLocalizedFolderExtension = @"localized";
NSString *const LFLocalizedFolderExtensionWithPeriod = @".localized";
NSString *const LFLocalizedFolderSubdirName = @".localized";

@implementation LFFolder

#pragma mark *** Checking Directory Permissions

+ (BOOL)isDirectoryAtPathSupported:(NSString *)path
{
    return [self canReadFromDirectoryAtPath:path];
}

+ (BOOL)isDirectoryAtURLSupported:(NSURL *)url
{
    return [self canReadFromDirectoryAtURL:url];
}

+ (BOOL)canReadFromDirectoryAtPath:(NSString *)path
{
    return [[NSFileManager defaultManager] isReadableFileAtPath:path];
}

+ (BOOL)canReadFromDirectoryAtURL:(NSURL *)url
{
    return [[NSFileManager defaultManager] isReadableFileAtPath:url.absoluteString];
}

+ (BOOL)canWriteToDirectoryAtPath:(NSString *)path
{
    return [[NSFileManager defaultManager] isWritableFileAtPath:path];
}

+ (BOOL)canWriteToDIrectoryAtURL:(NSURL *)url
{
    return [[NSFileManager defaultManager] isWritableFileAtPath:url.absoluteString];
}

#pragma mark *** Initialization ***

- (id)init
{
    self = [super init];
    if (self) {
        self.translations = [NSMutableDictionary new];
    }
    return self;
}

- (id)initWithURL:(NSURL *)url
{
    self = [self init];
    if (self) {
        [self loadTranslationsFromURL:url];
    }
    return self;
}

- (id)initWithURL:(NSURL *)url error:(NSError *__autoreleasing *)error
{
    self = [self init];
    if (self) {
        [self loadTranslationsFromURL:url error:error];
    }
    return self;
}

- (id)initWithFileWrapper:(NSFileWrapper *)fileWrapper
{
    self = [self init];
    if (self) {
        [self loadTranslationsFromFileWrapper:fileWrapper];
    }
    return self;
}

- (id)initWithFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error
{
    self = [self init];
    if (self) {
        [self loadTranslationsFromFileWrapper:fileWrapper error:NULL];
    }
    return self;
}

#pragma mark *** Getting the File Manager ***

- (NSFileManager *)fileManager
{
    return [NSFileManager defaultManager];
}

#pragma mark *** Loading Translations ***

- (BOOL)loadTranslationsFromURL:(NSURL *)url
{
    return [self loadTranslationsFromURL:url error:NULL];
}

- (BOOL)loadTranslationsFromURL:(NSURL *)url error:(NSError *__autoreleasing *)error
{
    self.folderName = [self folderNameForURL:url];
    NSURL *localizedDirectoryURL = [url URLByAppendingPathComponent:LFLocalizedFolderSubdirName isDirectory:YES];
    if ([self.fileManager fileExistsAtPath:localizedDirectoryURL.path]) {
        NSArray *localizationFileURLs = [self.fileManager contentsOfDirectoryAtURL:localizedDirectoryURL includingPropertiesForKeys:nil options:0 error:error];
        if (!localizationFileURLs) {
            return NO;
        }
        for (NSURL *localizationFile in localizationFileURLs) {
            if (![self addTranslationFromURL:localizationFile error:error]) {
                return NO;
            }
        }
        return YES;
    } else {
        // translations dictionary was initialized during [self init]
        return YES;
    }
}

- (BOOL)loadTranslationsFromFileWrapper:(NSFileWrapper *)fileWrapper
{
    return [self loadTranslationsFromFileWrapper:fileWrapper error:NULL];
}

- (BOOL)loadTranslationsFromFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error
{
    self.folderName = [self folderNameForFileWrapper:fileWrapper];
    NSFileWrapper *localizedDirectoryWrapper = fileWrapper.fileWrappers[LFLocalizedFolderSubdirName];
    if (localizedDirectoryWrapper) {
        for (NSFileWrapper *localizationFile in localizedDirectoryWrapper.fileWrappers) {
            if (![self addTranslationFromFileWrapper:localizationFile error:error]) {
                return NO;
            }
        }
        return YES;
    } else {
        // translations dictionary was initialized during [self init]
        return YES;
    }
}

- (BOOL)addTranslationFromURL:(NSURL *)url error:(NSError *__autoreleasing *)error
{
    NSString *localeID = [self localeIdentifierForURL:url];
    return [self addTranslationFromURL:url forLocale:localeID error:error];
}

- (BOOL)addTranslationFromFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error
{
    NSString *localeID = [self localeIdentifierForFileWrapper:fileWrapper];
    return [self addTranslationFromFileWrapper:fileWrapper forLocale:localeID error:error];
}

- (NSString *)localeIdentifierForURL:(NSURL *)url
{
    return url.lastPathComponent.stringByDeletingPathExtension;
}

- (NSString *)localeIdentifierForFileWrapper:(NSFileWrapper *)fileWrapper
{
    NSString *localeID = fileWrapper.filename;
    if (localeID.length == 0) {
        localeID = fileWrapper.preferredFilename;
    }
    localeID = localeID.stringByDeletingPathExtension;
    return localeID;
}

- (BOOL)addTranslationFromURL:(NSURL *)url forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error
{
    NSString *stringsFile = [NSString stringWithContentsOfURL:url usedEncoding:NULL error:error];
    if (!stringsFile) {
        return NO;
    }
    return [self addTranslationFromStringsFile:stringsFile forLocale:localeID error:error];
}

- (BOOL)addTranslationFromFileWrapper:(NSFileWrapper *)fileWrapper forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error
{
    NSString *stringsFile = [[NSString alloc] initWithData:fileWrapper.serializedRepresentation encoding:NSUnicodeStringEncoding];
    if (!stringsFile) {
        return NO;
    }
    return [self addTranslationFromStringsFile:stringsFile forLocale:localeID error:error];
}

- (BOOL)addTranslationFromStringsFile:(NSString *)stringsFile forLocale:(NSString *)localeID error:(NSError *__autoreleasing *)error
{
    NSDictionary *translationDict = stringsFile.propertyListFromStringsFileFormat;
    if (translationDict.count > 0) {
        NSString *value = translationDict.allValues[0];
        self.translations[localeID] = value;
    }
    return YES;
}

#pragma mark *** Saving Translations ***

- (BOOL)saveTranslationsToURL:(NSURL *)url
{
    return [self saveTranslationsToURL:url error:NULL];
}

- (BOOL)saveTranslationsToURL:(NSURL *)url error:(NSError *__autoreleasing *)error
{
    NSURL *localizedDirectoryURL = [url URLByAppendingPathComponent:LFLocalizedFolderSubdirName isDirectory:YES];
    [self.fileManager removeItemAtURL:localizedDirectoryURL error:NULL]; // If deleting fails continue, maybe we can just replace any existing subfiles.
    if (![self.fileManager createDirectoryAtURL:localizedDirectoryURL withIntermediateDirectories:YES attributes:nil error:error]) {
        return NO;
    }
    NSString *folderName;
    if (self.folderName.length > 0) {
        folderName = self.folderName;
    } else {
        folderName = [self folderNameForURL:url];
    }
    for (NSString *localeID in self.translations.allKeys) {
        NSString *filename = [NSString stringWithFormat:@"%@.strings", localeID];
        NSURL *fileURL = [localizedDirectoryURL URLByAppendingPathComponent:filename];
        NSString *stringsFile = @{folderName: self.translations[localeID]}.descriptionInStringsFileFormat;
        if (![stringsFile writeToURL:fileURL atomically:YES encoding:NSUnicodeStringEncoding error:error]) {
            return NO;
        }
    }
    return YES;
}

- (BOOL)saveTranslationsToFileWrapper:(NSFileWrapper *)fileWrapper
{
    return [self saveTranslationsToFileWrapper:fileWrapper error:NULL];
}

- (BOOL)saveTranslationsToFileWrapper:(NSFileWrapper *)fileWrapper error:(NSError *__autoreleasing *)error
{
    NSFileWrapper *localizedDirectoryWrapper = fileWrapper.fileWrappers[LFLocalizedFolderSubdirName];
    if (localizedDirectoryWrapper) {
        [fileWrapper removeFileWrapper:localizedDirectoryWrapper];
    }
    NSString *folderName;
    if (self.folderName.length > 0) {
        folderName = self.folderName;
    } else {
        folderName = [self folderNameForFileWrapper:fileWrapper];
    }
    localizedDirectoryWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:@{}];
    localizedDirectoryWrapper.preferredFilename = LFLocalizedFolderSubdirName;
    for (NSString *localeID in self.translations.allKeys) {
        NSString *filename = [NSString stringWithFormat:@"%@.strings", localeID];
        NSString *stringsFile = @{folderName: self.translations[localeID]}.descriptionInStringsFileFormat;
        NSData *stringsData = [stringsFile dataUsingEncoding:NSUnicodeStringEncoding];
        if (!stringsData) {
            return NO;
        }
        [localizedDirectoryWrapper addRegularFileWithContents:stringsData preferredFilename:filename];
    }
    [fileWrapper addFileWrapper:localizedDirectoryWrapper];
    return YES;
}

- (NSString *)folderNameForURL:(NSURL *)url
{
    NSString *filename = url.lastPathComponent;
    if ([filename hasSuffix:LFLocalizedFolderExtensionWithPeriod]) {
        return filename.stringByDeletingPathExtension;
    }
    return filename;
}

- (NSString *)folderNameForFileWrapper:(NSFileWrapper *)fileWrapper
{
    NSString *filename = fileWrapper.filename;
    if (filename.length == 0) {
        filename = fileWrapper.preferredFilename;
    }
    if ([filename hasSuffix:LFLocalizedFolderExtensionWithPeriod]) {
        return filename.stringByDeletingPathExtension;
    }
    return filename;
}

@end
