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

#import "ECLayer.h"
#import "ServiceFunctions.h"

NSString *plistLayerTypeKey = @"LayerType"; // レイヤーのタイプ。これがクラスと結びつく
NSString *plistLayerAuxResourceNameKey = @"AuxFileName"; // 外部ファイル名を記憶するキー
NSString *plistLayerOriginKey = @"origin"; // origin
NSString *plistLayerSizeKey = @"size";   // size
NSString *plistLayerAlphaKey= @"alpha";  // alpha
NSString *plistLayerHideKey = @"hide";   // hide
NSString *plistLayerLockKey = @"lock";   // lock
NSString *plistLayerNameKey = @"name";   // name

static NSMutableDictionary *_layerTable;

@implementation ECLayer
@synthesize origin,size,hide,lock,name,alpha, scene;

+ (void)initialize
{
    if(self == [ECLayer class])
    {
        _layerTable = [[NSMutableDictionary alloc] init];
    }
}

+ (NSSet*)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
    if([key isEqualToString: @"bounds"])
        return [NSSet setWithObjects: @"origin", @"size", nil];
    if([key isEqualToString: @"center"])
        return [NSSet setWithObjects: @"origin", @"size", nil];
    return [super keyPathsForValuesAffectingValueForKey: key];
}

+ (void)registerClass:(Class)layerClass
{
    [_layerTable setObject: layerClass forKey: [layerClass type]];
}

+ (id)layerWithPropertyList:(NSDictionary*)plist
                 packageURL:(NSURL*)aURL
{
    id type = [plist objectForKey: plistLayerTypeKey];
    Class Layer = [_layerTable objectForKey: type];
    if(Layer == nil)
        return nil;
    
    return [[[Layer alloc] initWithPropertyList: plist
                                     packageURL: aURL] autorelease];
}

- (id)initWithCoder:(NSCoder *)coder 
{
    name = [[coder decodeObjectForKey: plistLayerNameKey] copy];
    origin = [coder decodePointForKey: plistLayerOriginKey];
    size = [coder decodeSizeForKey: plistLayerSizeKey];
    alpha = [coder decodeFloatForKey: plistLayerAlphaKey];
    self.hide = [coder decodeBoolForKey: plistLayerHideKey];
    self.lock = [coder decodeBoolForKey: plistLayerLockKey];

    return self;
}

- (void)encodeWithCoder:(NSCoder*)encoder
{
    NSAssert([encoder allowsKeyedCoding], @"ECLayer dosen't support non-keyed achirve.");
    [encoder encodeObject: name forKey: plistLayerNameKey];
    [encoder encodePoint: origin forKey: plistLayerOriginKey];
    [encoder encodeSize: size forKey: plistLayerSizeKey];
    [encoder encodeFloat: alpha forKey: plistLayerAlphaKey];
    [encoder encodeBool: self.hide forKey: plistLayerHideKey];
    [encoder encodeBool: self.lock forKey: plistLayerLockKey];
}

+ (NSString*)type
{
    return nil;
}

- (id)init
{
    name = @"";
    alpha = 1.0;
    return self;
}

- (id)initWithPropertyList:(NSDictionary*)plist
                packageURL:(NSURL*)aURL
{
    id originData = [plist objectForKey: plistLayerOriginKey];
    id sizeData = [plist objectForKey: plistLayerSizeKey];
    origin = _pointFromData(originData);
    size = _sizeFromData(sizeData);
    alpha = [[plist objectForKey: plistLayerAlphaKey] floatValue];
    self.hide = [[plist objectForKey: plistLayerHideKey] boolValue];
    self.lock = [[plist objectForKey: plistLayerLockKey] boolValue];
    name = [[plist objectForKey: plistLayerNameKey] copy];
    
    // 外部ファイルの処理
    // id auxfile = [plist objectForKey: plistLayerAuxResourceNameKey]
    // id url = _layerResourceURLForName(aURL, auxfile);
    // でリソースにアクセス
    return self;
}

- (void)dealloc
{
    [name release];
    [super dealloc];
}

+ (id)undoObservationKeys
{
    return [NSMutableSet setWithObjects: @"origin", @"size", @"alpha", @"lock", @"hide", @"name", nil];
}

- (id)valueForUndefinedKey:(NSString *)key
{
    return NSNotApplicableMarker;
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    // 単に無視する
}

- (id)copyWithZone:(NSZone *)zone
{
    ECLayer *ret = [[[self class] allocWithZone: zone] init];
    ret->origin = origin;
    ret->size = size;
    ret->alpha = alpha;
    ret.hide = self.hide;
    ret.lock = self.lock;
    ret.name = self.name;
    return ret;
}

- (NSURL*)auxResourceURL
{
    // 使用中の外部ファイルのURLを返す
    // 保存時にはtypeを維持してrenameされたリソースをこれをもとに作成し、
    // propertyListWithAuxResourceNameが呼ばれる
    return nil;
}

- (id)propertyListWithAuxResourceName:(NSString*)filename
{
    // リソースは保存時にリネームされてハードリンクするので、
    // 構成時のオリジナルとは違う名前になる
    id originData = _pointToData(origin);
    id sizeData = _sizeToData(size);
    id hide_ = [NSNumber numberWithBool: self.hide];
    id lock_ = [NSNumber numberWithBool: self.lock];
    id alpha_ = [NSNumber numberWithFloat: alpha];
    
    id plist = [NSMutableDictionary dictionary];
    [plist setObject: [[self class] type] forKey: plistLayerTypeKey];
    [plist setObject: originData forKey: plistLayerOriginKey];
    [plist setObject: alpha_ forKey: plistLayerAlphaKey];
    [plist setObject: sizeData forKey: plistLayerSizeKey];
    [plist setObject: hide_ forKey: plistLayerHideKey];
    [plist setObject: lock_ forKey: plistLayerLockKey];
    if(name != nil)
        [plist setObject: name forKey: plistLayerNameKey];
    if(filename != nil)
        [plist setObject: filename forKey: plistLayerAuxResourceNameKey];
    
    // 本来はimmutable copyを返すべきだが、どうせ抽象クラスなのでズルをする!
    return plist;
}

- (BOOL)isStatic
{
    return YES;
}
#pragma mark Test
- (CGRect)bounds
{
    CGRect rect;
    rect.origin = origin;
    rect.size = size;
    return rect;
}

- (CGPoint)center
{
    CGFloat x = floor(origin.x + size.width/2.0);
    CGFloat y = floor(origin.y + size.height/2.0);
    return CGPointMake(x,y);
}

- (BOOL)pointInRect:(CGPoint)aPoint
{
    CGRect rect;
    rect.origin = origin;
    rect.size = size;
    return CGRectContainsPoint(rect,aPoint);
}

- (void)renderAtTime:(NSUInteger)msec
           inContext:(CGContextRef)context
{
    
}

- (void)renderInContext:(CGContextRef)context
{
    
}

- (void)renderThumbnailInContext:(CGContextRef)context
{
    
}

- (void)cleanupRendering
{
    
}

- (void)drawFrameWithColor:(NSColor*)aColor
{
    NSRect rect;
    rect.origin = NSPointFromCGPoint(origin);
    rect.size = NSSizeFromCGSize(size);
    rect = NSInsetRect(rect, -8.0, -8.0);
    id bp = [NSBezierPath bezierPathWithRoundedRect: rect xRadius: 3.0 yRadius: 3.0];
    [bp setLineWidth: 3.0];
    [aColor set];
    
    [bp stroke];
}

@end
