//
//  ECStoryboardPanelController.m
//  Etokicho
//
//  Created by 二鏡 on 11/11/21.
//  Copyright 2011年 二鏡庵. All rights reserved.
//

#import "ECStoryboardPanelController.h"
#import "MainController.h"
#import "ECTransitionEditorPanelController.h"
#import "ECDSceneSegment.h"
#import "ECDTransitionSegment.h"

extern NSString *udStoryboardShowPopover;

static NSString *oSelectedSegmentsContext = @"SeletedSegments";
static id _si = nil;

@implementation ECStoryboardPanelController
+ (id)sharedPanel
{
    if(_si == nil)
    {
        _si = [[self alloc] initWithWindowNibName: @"StoryboardPanel"];
        [_si window];
    }
    return _si;
}
- (void)awakeFromNib
{
    id tm = [[NSApp delegate] timelineManager];
    [view bind: @"content"
      toObject: tm
   withKeyPath: @"timeline.segments"
       options: nil];
    [view bind: @"selectedIndexes"
      toObject: tm
   withKeyPath: @"selection"
       options: nil];

    [view setTarget: self];
    [view setAction: @selector(testPopover:)];
    [view setDoubleAction: @selector(cancelPopover:)];
    [view setDelegate: self];
    
    [[NSNotificationCenter defaultCenter]
     addObserver: self
     selector: @selector(userDefaultsDidChange:) 
     name: NSUserDefaultsDidChangeNotification
     object: nil];
    
    [self setWindowFrameAutosaveName: @"StoryboardPanelFrame"];
}

- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window
{
    return [[[NSApp delegate] timelineManager] undoManager];
}

- (void)_tryOpenPopover:(id)sender
{
    id segment = [[[NSApp delegate] timelineManager] selectedSegment];
    if(segment == NSNoSelectionMarker || 
       segment == NSMultipleValuesMarker ||
       [segment isKindOfClass: [ECDTransitionSegment class]])    {
        // 一応失敗したら閉じる
        [popover close];
        return;
    }
    ECScene *scene = [segment scene];
    [sceneView.scene cleanupRendering];
    sceneView.scene = scene;
    
    id aView = [view enclosingScrollView];
    [sceneView setFrameSize: scene.size];
    [popover showRelativeToRect: [aView bounds]
                         ofView: aView
                  preferredEdge: CGRectMaxYEdge];
    
}

- (IBAction)testPopover:(id)sender
{
    if([[NSUserDefaults standardUserDefaults ] boolForKey: udStoryboardShowPopover] == NO)
        return;
    
    id selection = [[[NSApp delegate] timelineManager] selection];
    if([selection count] == 1)
        [NSApp sendAction: @selector(requestPopover:) 
                       to: [[self window] windowController]
                     from: self];
    else
        [NSApp sendAction: @selector(closePopover:) 
                       to: [[self window] windowController]
                     from: self];
  
    // いい文脈ならpopover
}

- (void)_editTransition:(id)sender
{
    ECTimelineManager *tm = [[NSApp delegate] timelineManager];
    ECDTransitionSegment *segment = (ECDTransitionSegment*)[tm selectedSegment];
    if(segment == NSNoSelectionMarker || 
       segment == NSMultipleValuesMarker ||
       [segment isKindOfClass: [ECDTransitionSegment class]] == NO)
        return;
    
    // editorを呼び出す
    ECTransitionEditorPanelController *editor = [ECTransitionEditorPanelController sharedTransitionEditor];
    
    id scenes = [tm aroundScenesOfSelectedSegment];
    id prev = [scenes objectAtIndex: 0];
    id next = [scenes objectAtIndex: 1];

    // できるだけカスタムイメージ
    if(prev != NSNotApplicableMarker && next != NSNotApplicableMarker)
    {
        CGImageRef imgSrc = [prev allocOutFrameImage];
        CGImageRef imgDst = [next allocInFrameImage];
        editor.customSource = imgSrc;
        editor.customDestination = imgDst;
        CFRelease(imgSrc);
        CFRelease(imgDst);
    }
    // パラメータをロード
    ECQCCompositionItem *item = segment.item;
    editor.name = segment.templateName;
    editor.compositionID = item.identifier;
    editor.flipHorizontal = segment.flipHorizontal;
    editor.parameters = item.parameters;
    editor.duration = (NSInteger)segment.msec;
    [editor loadCompositionWithParameters];
    
    // エディタに遷移
    NSUInteger result = [editor startModal];
    
    // クリーン
    editor.customSource = nil;
    editor.customDestination = nil;
    if(result != NSOKButton)
        return;

    // かきもどし
    id name = editor.name;
    id identifier = editor.compositionID;
    id parameters = editor.parameters;
    BOOL isFlipped = editor.flipHorizontal;
    NSInteger duration = editor.duration;
    
    if([name isEqualToString: segment.templateName])
    { // 名前が変更されていない場合、特殊化する
        id fmt = @"%@'";
        name = [NSString stringWithFormat: fmt, name];
    }
    
    item = [[[ECQCCompositionItem alloc] init] autorelease];
    item.identifier = identifier;
    item.parameters = parameters;
    segment.templateName = name;
    segment.item = item;
    segment.flipHorizontal = isFlipped;
    segment.msec = duration;
}

- (IBAction)requestPopover:(id)sender
{
    [[self class] cancelPreviousPerformRequestsWithTarget: self
                                                 selector: @selector(_tryOpenPopover:)
                                                   object: self];
    if(popover.isShown)
        [self _tryOpenPopover: self];
    else
        [self performSelector: @selector(_tryOpenPopover:)
                   withObject: self
                   afterDelay: 0.3];
}

- (IBAction)cancelPopover:(id)sender
{
    [[self class] cancelPreviousPerformRequestsWithTarget: self
                                                 selector: @selector(_tryOpenPopover:)
                                                   object: self];
}

- (IBAction)editTransition:(id)sender
{
    [self performSelector: @selector(_editTransition:)
               withObject: self
               afterDelay: 0.0];
}

- (IBAction)closePopover:(id)sender
{
    [popover close];
}

- (void)windowDidResignKey:(NSNotification *)notification
{
    [popover close];
}

- (void)userDefaultsDidChange:(id)sender
{
    if([[sender object] boolForKey: udStoryboardShowPopover] == NO)
    {
        if(popover.isShown)
        {
            [popover close];
        }
    }
    else
    {
        if([[self window] isKeyWindow])
        {
            if(popover.isShown == NO)
            {
                [self _tryOpenPopover: self];
            }
        }
    }
}

- (void)popoverDidShow:(NSNotification*)notification
{
    [[self window] makeFirstResponder: view];
}

- (void)popoverDidClose:(NSNotification *)notification
{
    [sceneView.scene cleanupRendering];
    sceneView.scene = nil;
}

#pragma mark Storyboard delegate
- (void)deleteSelection:(ECStoryboardView*)sender
{
    id tm = [[NSApp delegate] timelineManager];
    [[tm timeline] removeSegmentsAtIndexes: [tm selection]];
}

- (void)copySelection:(ECStoryboardView*)sender
{
    id tm = [[NSApp delegate] timelineManager];
    id segments = [[[tm timeline] segments] objectsAtIndexes: [tm selection]];
    id items = [NSMutableArray array];
    for(id segment in segments)
    {
        id URIString = [[[segment objectID] URIRepresentation] absoluteString];
        id item = [[NSPasteboardItem alloc] init];
        [item setString: URIString forType: ECDPasteboardTypeSegment];
        [items addObject: item];
        [item release];
    }
    
    id pboard = [NSPasteboard generalPasteboard];
    [pboard clearContents];
    [pboard writeObjects: items];
}

- (NSArray*)readSegmentsFromPasteboard_
{
    id pboard = [NSPasteboard generalPasteboard];
    id types = [NSArray arrayWithObject: ECDPasteboardTypeSegment];
    BOOL ok = [pboard canReadItemWithDataConformingToTypes: types];
    if(!ok)
        return nil;
    
    // NSPasteboardItemで取り出す
    id classArray = [NSArray arrayWithObject: [NSPasteboardItem class]];
    id opts = [NSDictionary dictionary];
    id items = [pboard readObjectsForClasses: classArray options: opts];
    id URIs = [NSMutableArray array];
    for(id item in items)
    {
        id URIString = [item stringForType: ECDPasteboardTypeSegment];
        id URI = [NSURL URLWithString: URIString];
        [URIs addObject: URI];
    }
    
    id tm = [[NSApp delegate] timelineManager];

    // この時点で生きているsegmentのみが戻ってくる    
    return [tm cloneSegments: [tm segmentsOfObjectIDURIs: URIs]];
}

- (void)pasteOnSelection:(ECStoryboardView*)sender
{
    id segments = [self readSegmentsFromPasteboard_];
    
    if([segments count] == 0) // nil時も含む
        return ;
    
    id tm = [[NSApp delegate] timelineManager];
    id timeline = [tm timeline];
    id selection = [tm selection];
        
    if([selection count] != 0)
    {
        // 削除してfirstに挿入
        [timeline removeSegmentsAtIndexes: selection];
        NSUInteger idx = [selection firstIndex];
        id indexes = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(idx, [segments count])];
        [timeline insertSegments: segments atIndexes: indexes];
    }
    else
    {
        // 末尾に追加
        [timeline addSegments: segments];
    }
}

- (void)pasteAfterSelection:(ECStoryboardView*)sender
{
    id segments = [self readSegmentsFromPasteboard_];
    
    if([segments count] == 0) // nil時も含む
        return ;
    
    id tm = [[NSApp delegate] timelineManager];
    id timeline = [tm timeline];
    id selection = [tm selection];
    
    if([selection count] != 0)
    {
        // lastの直後に挿入
        NSUInteger idx = [selection lastIndex]+1;
        id indexes = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(idx, [segments count])];
        [timeline insertSegments: segments atIndexes: indexes];
    }
    else
    {
        // 末尾に追加
        [timeline addSegments: segments];
    }
    
}

- (void)pasteBeforeSelection:(ECStoryboardView*)sender
{
    id segments = [self readSegmentsFromPasteboard_];
    
    if([segments count] == 0) // nil時も含む
        return ;
    
    id tm = [[NSApp delegate] timelineManager];
    id timeline = [tm timeline];
    id selection = [tm selection];
    
    if([selection count] != 0)
    {
        // firstに挿入
        NSUInteger idx = [selection firstIndex];
        id indexes = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(idx, [segments count])];
        [timeline insertSegments: segments atIndexes: indexes];
    }
    else
    {
        // 先頭に追加
        id indexes = [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [segments count])];
        [timeline insertSegments: segments atIndexes: indexes];
    }
}

@end

@implementation ECStoryboardPanelController (ToolTips)
- (NSString *)storyboardToolTip
{
    return NSLocalizedString(@"Double clicking on selection loads the scene as template.", @"");
}
@end
