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

#import "ECCompositionEditorPanelController.h"

static id _si;

@interface ECCompositionEditorPanelController (Simulation)
- (void)_startSimulation;
- (void)_stopSimulation;
@end

@interface ECCompositionEditorPanelController ()
@property (readwrite) BOOL hasProtocol;
@end

@implementation ECCompositionEditorPanelController
@synthesize filter,compositionName, hasProtocol, allowsSimulate;

+ (id)sharedPostEffectEditor
{
    if(_si == nil)
        _si = [[ECCompositionEditorPanelController alloc] initWithWindowNibName: @"CompositionEditor"];
    [_si window];
    return _si;
                  
}

- (void)awakeFromNib
{
    [[self window] useOptimizedDrawing: YES];
    popover.behavior = NSPopoverBehaviorTransient;
    [pickerView setShowsCompositionNames: YES];
    [pickerView setDrawsBackground: YES];
    [pickerView setAllowsEmptySelection: YES];
    NSImage *image = [NSImage imageNamed: @"Sample1"];
    CGSize size = [image size];
    [pickerView resetDefaultInputValues];
    [pickerView setDefaultValue: image
                    forInputKey: QCCompositionInputImageKey];
    [pickerView setCompositionAspectRatio: size];
}

- (void)attachRenderer:(QCComposition*)composition
{
    id renderer = [[sampleView target] attachRenderer: composition];
    [parameterView setCompositionRenderer: renderer];
    [sampleView setNeedsDisplay: YES];
}

- (void)loadScene:(ECScene*)scene
       layerIndex:(NSUInteger)index
{
    [sampleView setContent: scene
               targetLayer: index];
    ECLayer <QCLayer> *target = [sampleView target];

    ECQCCompositionItem *item = target.compositionItem;
    if([target isUseEmbeddedComposition])
    {
        // 野良コンポジションを使う場合はpicker viewを用いない
        id comp = [target loadEmbeddedComposition];
        self.compositionName = [[comp attributes] valueForKeyPath: QCCompositionAttributeNameKey];
        target.compositionItem = nil;
        [self attachRenderer: comp];
        [item apply: [parameterView compositionRenderer]];        
    }
    else
    {
        // もしsceneがcompositionを持っていたらここでpickerViewに設定
        if(item)
        {
            id comp = [item loadComposition];
            self.compositionName = [[comp attributes] valueForKey: QCCompositionAttributeNameKey];
            
            // targetはcompositionもコピーしているが、そのままだとパラメータの変更を受け付けないので、
            // rendererだけで機能するようにクリアする
            target.compositionItem = nil; 
            
            [pickerView setSelectedComposition: comp];
            [self attachRenderer: comp];
            [item apply: [parameterView compositionRenderer]];
        }
        else
        {
            self.compositionName = nil;
            [pickerView setSelectedComposition: nil];
            [parameterView setCompositionRenderer: nil];
        }
    }
}

- (void)setProtocol:(NSString*)aProtocol
{
    if(aProtocol)
        [pickerView setCompositionsFromRepositoryWithProtocol: aProtocol
                                                andAttributes: nil];
    self.hasProtocol = aProtocol != nil;
}

- (NSInteger)startModal
{
    id center = [NSNotificationCenter defaultCenter];
    [center addObserver: self
               selector: @selector(compositionDidChange:)
                   name: QCCompositionPickerViewDidSelectCompositionNotification
                 object: pickerView];
    [pickerView startAnimation: self];

    NSWindow *window = [self window];
    [window center];
    
    NSInteger result = [NSApp runModalForWindow: window];
    
    // 現在のパラメータを作って返す
    self.filter = [sampleView.target currentRendererParameters];
    
    [center removeObserver: self
                      name: QCCompositionPickerViewDidSelectCompositionNotification
                    object: pickerView];
    [sampleView setContent: nil targetLayer: 0];
    [pickerView setSelectedComposition: nil];
    [pickerView stopAnimation: self];
    
    return result;
}

- (void)compositionDidChange:(id)notif
{
    id composition = [pickerView selectedComposition];
    self.compositionName = [[composition attributes] valueForKey: QCCompositionAttributeNameKey];
    [self attachRenderer: composition];
    simulation.passed = 0.0;
    [popover close];
}

- (void)compositionParameterView:(QCCompositionParameterView*)parameterView 
       didChangeParameterWithKey:(NSString*)portKey
{
    [sampleView setNeedsDisplay: YES];
}

- (BOOL)compositionParameterView:(QCCompositionParameterView *)parameterView
   shouldDisplayParameterWithKey:(NSString *)portKey
                      attributes:(NSDictionary *)portAttributes
{
    if([portKey isEqualToString: QCCompositionInputImageKey])
        return NO;
    return YES;
}

- (IBAction)ok:(id)sender
{
    if(simulation.timer)
        [self _stopSimulation];

    [NSApp stopModalWithCode: NSOKButton];
    [[self window] close];
}

- (IBAction)cancel:(id)sender
{
    if(simulation.timer)
        [self _stopSimulation];

    [NSApp stopModalWithCode: NSCancelButton];
    [[self window] close];
}

- (IBAction)showComposition:(id)sender
{
    [popover showRelativeToRect: [sender bounds]
                         ofView: sender
                  preferredEdge: NSMinYEdge];
}

- (IBAction)detach:(id)sender
{
    [pickerView setSelectedComposition: nil];
}

- (IBAction)simulate:(id)sender
{
    if(simulation.timer)
        [self _stopSimulation];
    else
        [self _startSimulation];
}
@end

@implementation ECCompositionEditorPanelController (Simulation)
- (void)_time:(NSTimer*)timer
{
    simulation.passed += [timer timeInterval];
    [sampleView setTime: simulation.passed*1000.0];
    [sampleView setNeedsDisplay: YES];
}

- (void)_startSimulation
{
    NSUInteger fps = 30; // テストは30fps固定とする
    NSTimeInterval interval = 1.0/fps;
    simulation.timer = [NSTimer timerWithTimeInterval: interval
                                               target: self
                                             selector: @selector(_time:) 
                                             userInfo: nil
                                              repeats: YES];
    simulation.passed = 0.0;
    [self willChangeValueForKey: @"simulating"];
    simulating = YES;
    [self didChangeValueForKey: @"simulating"];
    [[NSRunLoop currentRunLoop] addTimer: simulation.timer
                                 forMode: NSModalPanelRunLoopMode];
    [simulation.timer fire];
}

- (void)_stopSimulation
{
    [simulation.timer invalidate];
    simulation.timer = nil;
    [self willChangeValueForKey: @"simulating"];
    simulating = NO;
    [self didChangeValueForKey: @"simulating"];
    return ;    
}
@end
