//
//  ECSceneComposition.m
//  Etokicho
//
//  Created by 二鏡 on 11/12/02.
//  Copyright 2011年 二鏡庵. All rights reserved.
//

#import "ECSceneComposition.h"
#import "ECRegularLayer.h"
#import "ECLayer_Defaults.h"
#import "ECCompositionLayer.h"

static NSString *oLayersChangeContext = @"LayerChanged";
static NSString *oSceneUpdateContext = @"SceneUpdate";


@implementation ECSceneComposition
@synthesize selection, undo, selectedLayer;
+ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
    if([key isEqualToString: @"selectedLayer"])
        return [NSSet setWithObject: @"selection"];
    if([key isEqualToString: @"canUp"])
        return [NSSet setWithObject: @"selection"];
    if([key isEqualToString: @"canDown"])
        return [NSSet setWithObject: @"selection"];
    if([key isEqualToString: @"canDelete"])
        return [NSSet setWithObject: @"selection"];
    
    return [super keyPathsForValuesAffectingValueForKey: key];
}

- (id)init
{
    self = [super init];
    undo = [[NSUndoManager alloc] init];
    selectedLayer = [[ECLayerProxy alloc] init];
    // UI向けにズルをする
    id UISet = [NSSet setWithObjects: @"textX", @"textY", 
                @"textWidth", @"textHeight", @"fontName", nil];
    [selectedLayer registerForceKeys: [ECRegularLayer undoObservationKeys]];
    [selectedLayer registerForceKeys: [ECCompositionLayer undoObservationKeys]];
    [selectedLayer registerForceKeys: UISet];
    return self;
}

- (ECScene*)scene
{
    return scene;
}

- (void)setScene:(ECScene*)aScene
{
    if(scene == aScene)
        return;
    
    [self deselect];

    // release old
    [scene removeObserver: self forKeyPath: @"layers"];
    [scene removeObserver: self forKeyPath: @"update"];
    scene.undo = nil;
    [scene release];
    
    scene = [aScene retain];
    [scene addObserver: self
            forKeyPath: @"layers"
               options: 0
               context: oLayersChangeContext];
    [scene addObserver: self
            forKeyPath: @"update"
               options: 0
               context: oSceneUpdateContext];
    [undo removeAllActions];
    scene.undo = undo;
}

- (BOOL)update
{
    return YES;
}

- (void)setSelection:(NSIndexSet*)set
{
    if(selection == set)
        return;
    
    [selection release];
    selection = [set copy];
    if([selection count] == 1)
    {
        id layer = [scene objectInLayersAtIndex: [selection firstIndex]];
        [selectedLayer setTarget: layer];
    }
    else
        [selectedLayer setTarget: nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    if (context == oLayersChangeContext) {
        NSKeyValueChange type = [[change valueForKey: NSKeyValueChangeKindKey] unsignedIntegerValue];
        switch(type)
        {
            case NSKeyValueChangeRemoval:
                self.selection = [NSIndexSet indexSet];
                break;
            case NSKeyValueChangeInsertion:
                self.selection = [change valueForKey: NSKeyValueChangeIndexesKey];                
                break;
            case NSKeyValueChangeReplacement:
            case NSKeyValueChangeSetting:
                ;
        }
        return;
    } 
    
    if(context == oSceneUpdateContext)
    {
        [self willChangeValueForKey: @"update"];
        [self didChangeValueForKey: @"update"];
        return ;
    }
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}

- (void)exchangeLayersAtIndex:(NSUInteger)oldIndex
                         with:(NSUInteger)newIndex
{
    [scene exchangeLayerObjectAtIndex: oldIndex
                    withObjectAtIndex: newIndex];
}

- (void)add:(ECLayer*)layer
{
    [scene insertObject: layer
        inLayersAtIndex: 0];
}

- (void)select:(ECLayer*)aLayer
{
    NSUInteger idx = [scene.layers indexOfObject: aLayer];
    if(idx == NSNotFound)
        [self deselect];
    else
        self.selection = [NSIndexSet indexSetWithIndex: idx];
}

- (void)deselect
{
    self.selection = [NSIndexSet indexSet];
}

- (BOOL)canUp
{
    id layers = scene.layers;
    if([layers count] < 2)
        return NO;
    
    NSUInteger idx = [selection firstIndex];
    return idx != 0;
}

- (BOOL)canDown
{
    id layers = scene.layers;
    NSUInteger count = [layers count];
    if(count < 2)
        return NO;
    
    NSUInteger idx = [selection firstIndex];
    return idx != count-1;
}

- (BOOL)canDelete
{
    return [selection count] != 0;
}

- (void)up
{
    NSUInteger idx = [selection firstIndex];
    [self exchangeLayersAtIndex: idx
                           with: idx-1];
    self.selection = [NSIndexSet indexSetWithIndex: idx-1];
}

- (void)down
{
    NSUInteger idx = [selection firstIndex];
    [self exchangeLayersAtIndex: idx
                           with: idx+1];
    self.selection = [NSIndexSet indexSetWithIndex: idx+1];
}

- (void)insertRegular
{
    // デフォルトのレギュラーlayerを追加する
    NSUInteger idx = [selection firstIndex];
    if(idx == NSNotFound)
        idx = 0;
    
    CGSize size = scene.size;
    ECRegularLayer *newLayer = [[ECRegularLayer alloc] initWithImage: nil
                                                                size: CGSizeMake(128,128)]; // default size
    newLayer.font = [ECRegularLayer defaultFont];
    
    CGFloat dx = floor(size.width/2.0-64.0);
    CGFloat dy = floor(size.height/2.0-64.0);
    newLayer.origin = CGPointMake(dx,dy);
    newLayer.name = [scene nextLayerName];
    
    [scene insertObject: newLayer inLayersAtIndex: idx];
    [newLayer release];
}

- (void)insertAnimation
{
    NSUInteger idx = [selection firstIndex];
    if(idx == NSNotFound)
        idx = 0;
    
    CGSize size = scene.size;
    ECCompositionLayer *newLayer = [[ECCompositionLayer alloc] init];
    
    newLayer.origin = CGPointMake(0,0);
    newLayer.size = size;
    newLayer.name = NSLocalizedString(@"Animation Layer", @"");
    
    [scene insertObject: newLayer inLayersAtIndex: idx];
    [newLayer release];
}

- (void)remove
{
    id array = [scene mutableArrayValueForKey: @"layers"];
    [array removeObjectsAtIndexes: selection];
}

- (void)clear
{
    // clear selection & remove all
    id array = [scene mutableArrayValueForKey: @"layers"];
    [array removeAllObjects];
}
@end
