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

#import "ECLayerProxy.h"
#import "ECCompositionLayer.h"

static NSString *oLayerValueChangeContext = @"LayerValueChange";
extern NSString *udKeepAspect;

@implementation ECLayerProxy
@synthesize target;

+ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
    if([key isEqualToString: @"x"])
        return [NSSet setWithObject: @"origin"];
    if([key isEqualToString: @"y"])
        return [NSSet setWithObject: @"origin"];
    if([key isEqualToString: @"width"])
        return [NSSet setWithObject: @"size"];
    if([key isEqualToString: @"height"])
        return [NSSet setWithObject: @"size"];
    if([key isEqualToString: @"isCompositionLayer"])
        return [NSSet setWithObject: @"target"];
    return [super keyPathsForValuesAffectingValueForKey: key];
}

- (id)init
{
    self = [super init];
    keepAspect = [[NSUserDefaults standardUserDefaults]
                  boolForKey: udKeepAspect];
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(userDefaultsChanged:)
                                                 name: NSUserDefaultsDidChangeNotification
                                               object: nil];
    forceKeys = [[NSMutableSet alloc] init];
    return self;
}

- (void)registerForceKeys:(NSSet*)keys
{
    [forceKeys unionSet: keys];
}

- (void)userDefaultsChanged:(id)notif
{
    keepAspect = [[NSUserDefaults standardUserDefaults]
                  boolForKey: udKeepAspect];
}

- (void)startObserving:(ECLayer*)aLayer
{
    id keys = [[aLayer class] undoObservationKeys];
    for(id key in keys)
    {
        [aLayer addObserver: self 
                 forKeyPath: key
                    options: (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
                    context: oLayerValueChangeContext];
    }
}

- (void)stopObserving:(ECLayer*)aLayer
{
    id keys = [[aLayer class] undoObservationKeys];
    for(id key in keys)
    {
        [aLayer removeObserver: self
                    forKeyPath: key];
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context {
    if (context == oLayerValueChangeContext)
    {
        // 実体が変化した時にproxyも変化(のフリ)
        [self willChangeValueForKey: keyPath];
        [self willChangeValueForKey: @"update"];
        [self didChangeValueForKey: @"update"];
        [self didChangeValueForKey: keyPath];
        return;
    }
    
    return [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}

- (void)setTarget:(ECLayer*)aLayer
{
    if(target == aLayer)
        return;
    
    for(id key in forceKeys)
        [self willChangeValueForKey: key];
    
    [self stopObserving: target];
    target = aLayer;
    [self startObserving: target];
    
    for(id key in forceKeys)
        [self didChangeValueForKey: key];
}

- (BOOL)update
{
    return YES;
}

- (CGFloat)x
{
    return target.origin.x;
}

- (void)setX:(CGFloat)x
{
    CGPoint origin = target.origin;
    origin.x = x;
    target.origin = origin;
}

- (CGFloat)y
{
    return target.origin.y;
}

- (void)setY:(CGFloat)y
{
    CGPoint origin = target.origin;
    origin.y = y;
    target.origin = origin;
}

- (CGFloat)width
{
    return target.size.width;
}

- (void)setWidth:(CGFloat)width
{
    CGSize size = target.size;
    if(keepAspect)
    {
        CGFloat ratio = size.height/size.width;
        size.height = ratio*width;
        size.width = width;
    }
    else
    {
        size.width = width;
    }
    target.size = size;
}

- (CGFloat)height
{
    return target.size.height;
}

- (void)setHeight:(CGFloat)height
{
    CGSize size = target.size;
    if(keepAspect)
    {
        CGFloat ratio = size.width/size.height;
        size.width = ratio*height;
        size.height = height;
    }
    else
    {
        size.height = height;
    } 
    target.size = size;
}

- (id)valueForUndefinedKey:(NSString *)key
{
    return [target valueForKey: key];
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    [target setValue: value forKey: key];
}

@end

@implementation ECLayerProxy (QCLayer)
- (BOOL)isCompositionLayer
{
    return [target isKindOfClass: [ECCompositionLayer class]];
}
@end
