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

#import "LFDocument.h"

void *const FolderNameChangedContext = @"FolderNameChangedContext";
void *const TranslationsChangedContext = @"TranslationsChangedContext";


@implementation LFDocument {
    NSString *_lastSavePanelEnteredFilename;
    NSString *_lastFolderName;
}

- (id)init
{
    self = [super init];
    if (self) {
        self.folder = [[LFFolder alloc] init];
    }
    return self;
}

- (void)setFolder:(LFFolder *)f
{
    [_folder removeObserver:self forKeyPath:@"translations"];
    [_folder removeObserver:self forKeyPath:@"folderName"];
    _folder = f;
    [_folder addObserver:self forKeyPath:@"translations" options:NSKeyValueObservingOptionOld context:TranslationsChangedContext];
    [_folder addObserver:self forKeyPath:@"folderName" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:FolderNameChangedContext];
}

- (void)dealloc
{
    [_folder removeObserver:self forKeyPath:@"translations"];
    [_folder removeObserver:self forKeyPath:@"folderName"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == TranslationsChangedContext) {
        NSMutableDictionary *oldValue = change[NSKeyValueChangeOldKey];
        [self.undoManager registerUndoWithTarget:self.folder selector:@selector(setTranslations:) object:oldValue];
    } else if (context == FolderNameChangedContext) {
        NSString *oldName = change[NSKeyValueChangeOldKey];
        NSString *newName = change[NSKeyValueChangeNewKey];
        [self renameFolderFrom:oldName to:newName];
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)renameFolderFrom:(id)oldName to:(id)newName
{
    if (oldName == [NSNull null] || !oldName) {
        // Ignore initial change
        return;
    }
    if ([oldName isEqual:newName]) {
        return;
    }
    if ([newName isEqual:self.fileURL.lastPathComponent.stringByDeletingPathExtension]) {
        return;
    }
    NSString *actualNewName = [newName stringByAppendingPathExtension:LFLocalizedFolderExtension];
    NSURL *newURL = [self.fileURL.URLByDeletingLastPathComponent URLByAppendingPathComponent:actualNewName isDirectory:YES];
    if ([[NSFileManager defaultManager] fileExistsAtPath:newURL.path]) {
        _lastFolderName = oldName;
        NSBeginAlertSheet(NSLocalizedString(@"The folder could not be renamed", nil), @"OK", nil, nil, self.windowForSheet, self, NULL, @selector(renameFolderSheetDidDismiss:returnCode:contextInfo:), NULL, NSLocalizedString(@"Another folder with the same name already exists at that location. Rename the existing folder or choose another name.", nil));
        return;
    }
    [self moveToURL:newURL completionHandler:^(NSError *error) {
        if (error) {
            [self presentError:error];
        }
    }];
}

- (void)renameFolderSheetDidDismiss:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void  *)contextInfo
{
    self.folder.folderName = _lastFolderName;
}

- (NSString *)windowNibName
{
    return @"LFDocument";
}

- (NSString *)autosavingFileType
{
    // Autosave is disabled
    return nil;
}

- (void)saveDocumentWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(void *)contextInfo
{
    if (!self.fileURL) {
        [super saveDocumentWithDelegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
    } else {
        NSString *title = NSLocalizedString(@"Do you want do delete the contents of the folder?", nil);
        NSString *deleteButton = NSLocalizedString(@"Delete Folder's Contents", nil);
        NSString *cancelButton = NSLocalizedString(@"Cancel", nil);
        NSString *applyButton = NSLocalizedString(@"Apply to...", nil);
        NSString *msgFormat = NSLocalizedString(@"If you save this document the contents of the folder will be deleted. If you want to keep the folder's contents select \"Apply to...\" and select the folder. In either way, this operation can not be undone.", nil);
        NSBeginCriticalAlertSheet(title, applyButton, cancelButton, deleteButton, self.windowForSheet, self, NULL, @selector(saveWarningSheetDidDismiss:returnCode:contextInfo:), NULL, @"%@", msgFormat);
    }
}

- (void)saveWarningSheetDidDismiss:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void  *)contextInfo
{
    if (returnCode == NSAlertDefaultReturn) {
        [self applyTo:self];
    } else if (returnCode == NSAlertOtherReturn) {
        [super saveDocumentWithDelegate:nil didSaveSelector:NULL contextInfo:NULL];
    }
}

- (IBAction)applyTo:(id)sender
{
    NSOpenPanel *openPanel = [NSOpenPanel openPanel];
    openPanel.canChooseDirectories = YES;
    openPanel.canChooseFiles = NO;
    openPanel.allowsMultipleSelection = NO;
    openPanel.canCreateDirectories = YES;
    openPanel.message = NSLocalizedString(@"Select a directory you want to apply the current translations to", nil);
    openPanel.prompt = NSLocalizedString(@"Select", nil);
    [openPanel beginSheetModalForWindow:self.windowForSheet completionHandler:^(NSInteger result) {
        if (result == NSFileHandlingPanelOKButton) {
            [self applyToURL:openPanel.URL];
        }
    }];
}

- (void)applyToURL:(NSURL *)url
{
    NSError *error;
    NSURL *actualURL = url;
    if (![actualURL.lastPathComponent hasSuffix:LFLocalizedFolderExtensionWithPeriod]) {
        actualURL = [actualURL URLByAppendingPathExtension:LFLocalizedFolderExtension];
        if ([[NSFileManager defaultManager] fileExistsAtPath:actualURL.path]) {
            NSRunAlertPanel(NSLocalizedString(@"The folder could not be localized", nil), NSLocalizedString(@"Another folder with the name \"%@\" already exists", nil), NSLocalizedString(@"OK", nil), nil, nil, actualURL.lastPathComponent);
            return;
        }
        [[NSFileManager defaultManager] moveItemAtURL:url toURL:actualURL error:&error];
        if (error) {
            [self presentError:error];
            return;
        }
    }
    LFFolder *folder = [[LFFolder alloc] initWithURL:actualURL error:&error];
    if (error) {
        [self presentError:error];
        return;
    }
    folder.translations = self.folder.translations.copy;
    [folder saveTranslationsToURL:actualURL error:&error];
    if (error) {
        [self presentError:error];
    }
}

- (BOOL)prepareSavePanel:(NSSavePanel *)savePanel
{
    savePanel.directoryURL = self.fileURL.URLByDeletingLastPathComponent;
    savePanel.delegate = self;
    return YES;
}

- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
{
    NSString *newName = filename;
    if (![newName hasSuffix:LFLocalizedFolderExtensionWithPeriod]) {
        newName = [newName stringByAppendingPathExtension:LFLocalizedFolderExtension];
    }
    _lastSavePanelEnteredFilename = newName;
    return newName;
}

- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
    if (!self.folder.folderName) {
        self.folder.folderName = _lastSavePanelEnteredFilename.stringByDeletingPathExtension;
    }
    return [self.folder saveTranslationsToURL:url error:outError];
}

- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
    self.folder = [[LFFolder alloc] init];
    return [self.folder loadTranslationsFromURL:url error:outError];
}

@end
