//
//  ECImageBrowserWindowController.m
//  SceneRenderProto
//
//  Created by 二鏡 on 11/11/15.
//  Copyright 2011年 二鏡庵. All rights reserved.
//

#import "ECImageBrowserWindowController.h"
#import "ECImageSourceItem.h"
#import "ECTemplateSourceItem.h"
#import "UTIs.h"

static NSString *udImageSourcePathKey = @"imageSourcePath";

static NSString *
_pathForPictures()
{
    id array = NSSearchPathForDirectoriesInDomains(NSPicturesDirectory, NSUserDomainMask, YES);
    return [array objectAtIndex: 0];    
}

typedef void (^panelHandler_t)(NSInteger);

static id _si = nil;

@implementation ECImageBrowserWindowController
+ (void)initialize
{
    id ud = [NSUserDefaults standardUserDefaults];
    id picture = _pathForPictures();
    id defs = [NSDictionary dictionaryWithObject: picture
                                          forKey: udImageSourcePathKey];
    [ud registerDefaults: defs];
}

+ (id)sharedBrowser
{
    if(_si == nil)
    {
        _si = [[self alloc] initWithWindowNibName: @"ImageBrowser"];
        [_si window];
    }
    return _si;
}

- (id)initWithWindow:(NSWindow *)window
{
    self = [super initWithWindow:window];
    if (self) {
        id bundle = [NSBundle mainBundle];
        id modelURL = [bundle URLForResource: @"ImageSourceItem"
                               withExtension: @"mom"];
         
        model = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL];
        id center = [NSNotificationCenter defaultCenter];
        [center addObserver: self
                   selector: @selector(folderContentDidChange:)
                       name: DictoryObserverFolderUpdateNotification
                     object: nil];
    }
    
    return self;
}

- (void)windowDidLoad
{
    [super windowDidLoad];
    
    id ud = [NSUserDefaults standardUserDefaults];
    id path = [ud stringForKey: udImageSourcePathKey];
    id fm = [NSFileManager defaultManager];
    if(![fm fileExistsAtPath: path
                 isDirectory: NULL])
        path = _pathForPictures();
    
    [self openFolder: [NSURL fileURLWithPath: path]];
    [self setWindowFrameAutosaveName: @"ImageBrowserFrame"];
}

- (void)folderContentDidChange:(id)notif
{
    [self openFolder: currentFolder];
}

- (void)_addImageObjects:(NSArray*)items
{
    for(NSString *aPath in items)
    {
        id obj = [NSEntityDescription insertNewObjectForEntityForName: @"ImageSourceItem"
                                               inManagedObjectContext: sourceContext];
        [obj setValue: aPath forKey: @"path"];
    }
}

- (void)loadFolderContent:(NSURL*)aURL
{
    [self willChangeValueForKey: @"sourceContext"];
    [sourceContext release];
    // renew image item context
    sourceContext = [[NSManagedObjectContext alloc] init];
    
    id coord = [[[NSPersistentStoreCoordinator alloc]
                initWithManagedObjectModel: model] autorelease];
    [coord addPersistentStoreWithType: NSInMemoryStoreType
                        configuration: nil
                                  URL: nil
                              options: nil
                                error: nil];
    [sourceContext setPersistentStoreCoordinator: coord];
    [self didChangeValueForKey: @"sourceContext"];
    
    id fm = [NSFileManager defaultManager];
    id ws = [NSWorkspace sharedWorkspace];
    
    // enumerate contents of folder
    NSError *error;
    id files = [fm contentsOfDirectoryAtURL: aURL
                 includingPropertiesForKeys: nil
                                    options: NSDirectoryEnumerationSkipsHiddenFiles
                                      error: &error];
    if(files == nil)
    {
        [NSApp presentError: error];
        return;
    }
    
    // test content type of each file
    for(NSURL *file in files)
    {
        ECImageSourceItem *obj;
        
        id path = [file path];
        id UTI = [ws typeOfFile: path error: &error];
        if(UTI == nil)
            continue;
        
        if(UTTypeConformsTo((CFStringRef)UTI, kUTTypeAliasFile))
        {
            // aliasを解決
            Boolean isDir,wasAlias;
            FSRef ref;
            char buf[1024];
            
            FSPathMakeRef((const UInt8*)[path UTF8String], &ref, NULL);
            FSResolveAliasFile(&ref, true, &isDir, &wasAlias);
            FSRefMakePath(&ref, (UInt8*)buf, 1024);
            
            // 解決先を解釈
            path = [NSString stringWithUTF8String: buf];
            UTI = [ws typeOfFile: path error: &error];
        }

        if(UTTypeConformsTo((CFStringRef)UTI, kUTTypeSymLink))
        {
            // シンボリックリンクを解決
            id dst = [fm destinationOfSymbolicLinkAtPath: path
                                                   error: nil];
            if(dst == nil)
                continue;
            
            // 相対パスならば変換
            if([dst isAbsolutePath] == NO)
            {
                path = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent: dst];
            }

            // 解決先を解釈
            UTI = [ws typeOfFile: path error: &error];
        }
        
        if(UTTypeConformsTo((CFStringRef)UTI, utiSceneFile))
        {
            obj = [NSEntityDescription insertNewObjectForEntityForName: @"TemplateSourceItem"
                                                inManagedObjectContext: sourceContext];
            [obj setValue: path forKey: @"path"];
            obj.isFolder = NO;
            continue;
        }

        if(UTTypeConformsTo((CFStringRef)UTI, kUTTypeFolder))
        {
            obj = [NSEntityDescription insertNewObjectForEntityForName: @"ImageSourceItem"
                                                                   inManagedObjectContext: sourceContext];
            [obj setValue: path forKey: @"path"];
            obj.isFolder = YES;
            continue;
        }
        
        if(UTTypeConformsTo((CFStringRef)UTI, kUTTypeImage))
        {
            obj = [NSEntityDescription insertNewObjectForEntityForName: @"ImageSourceItem"
                                                   inManagedObjectContext: sourceContext];
            [obj setValue: path forKey: @"path"];
            obj.isFolder = NO;
            continue;
        }
    }
}

- (void)openFolder:(NSURL*)aURL
{
    currentFolder = aURL;
    [navigator setURL: currentFolder];
    [observer stop];
    [observer release];
    [self loadFolderContent: currentFolder];
    observer = [[DirectoryObserver alloc] initWithTarget: [aURL path]];
    [observer start];

    // storing
    id ud = [NSUserDefaults standardUserDefaults];
    [ud setObject: [aURL path] forKey: udImageSourcePathKey];
}

- (NSArray*)sortDescriptors
{
    id title = [[[NSSortDescriptor alloc] initWithKey: @"imageTitle"
                                            ascending: YES] autorelease];
    id type = [[[NSSortDescriptor alloc] initWithKey: @"isFolder"
                                           ascending: NO] autorelease];
    return [NSArray arrayWithObjects: type, title,nil];
}

- (IBAction)runOpenPanel:(id)sender
{
    id panel = [NSOpenPanel openPanel];

    panelHandler_t handler = ^(NSInteger result) {
        if(result == NSFileHandlingPanelOKButton)
        {
            id URL = [panel directoryURL];
            [self openFolder: URL];
        }
    };

    [panel setDirectoryURL: [navigator URL]];
    [panel setAllowedFileTypes: [NSArray arrayWithObject: (id)kUTTypeFolder]];
    [panel setCanChooseDirectories: YES];
    [panel setResolvesAliases: YES];
    [panel beginWithCompletionHandler: handler];
}

- (IBAction)navigatorChange:(id)sender
{
    id cell = [navigator clickedPathComponentCell];
    id url = [cell URL];
    [self openFolder: url];
}
@end

@implementation ECImageBrowserWindowController (ImageKit)

- (void)imageBrowser:(IKImageBrowserView *)aBrowser
cellWasDoubleClickedAtIndex:(NSUInteger) index
{
    id ws = [NSWorkspace sharedWorkspace];
    
    id obj = [[itemsController arrangedObjects] objectAtIndex: index];
    id path = [obj valueForKey: @"path"];
    id UTI = [ws typeOfFile: path error: nil];
    
    if(UTTypeConformsTo((CFStringRef)UTI, kUTTypeFolder))
    {
        [self openFolder: [NSURL fileURLWithPath: path]];
    }
}

- (NSUInteger)imageBrowser:(IKImageBrowserView *)aBrowser
       writeItemsAtIndexes:(NSIndexSet *)itemIndexes
              toPasteboard:(NSPasteboard *)pasteboard
{
    // image fileでないならば0を返す
    NSUInteger index = [itemIndexes firstIndex];
    id ws = [NSWorkspace sharedWorkspace];
    
    id obj = [[itemsController arrangedObjects] objectAtIndex: index];
    id path = [obj valueForKey: @"path"];
    id UTI = [ws typeOfFile: path error: nil];
    
    // フォルダはドラッグできない
    if(UTTypeConformsTo((CFStringRef)UTI, kUTTypeFolder))
    {
        return 0;
    }
    
    // 必ずイメージである
    // URLのドラッグはFinderに落とすと怪しくなるのだが、気にするべきではないのか？
    id items = [NSArray arrayWithObject: [NSURL fileURLWithPath: path]];
    [pasteboard clearContents];
    [pasteboard writeObjects: items];
    return 1;
}
@end
