//
//  CRSceneItemBase.h
//  CRGraphics
//
//  Created by Yaroslav Glushchenko on 10/25/10.
//  Copyright 2010 Corner-A. All rights reserved.
//

#import "CRPortsManager.h"

extern NSString* CRSceneItemChainingAll;

//////////////////////////////////////////////////////////////////////
// Base scene item
//////////////////////////////////////////////////////////////////////
@interface CRSceneItemBase : NSObject<NSCoding, NSCopying, CREmbeddedResourcesContainer, CRPortsOwner>
{	
	BOOL						isLoaded;
	
@protected
	CRScene* assigned			rootScene;
	CRSceneItemBase* assigned	superItem;
	NSMutableArray*				subItems;
	CRPortsManager*				ports;
	id							tag;
	
	// chaining
	id							chainSource;
	NSString*					chainSubsetID;
	NSArray*					chainedData;
	BOOL						restrictDeepChain;
	
@protected
	NSMutableDictionary*		obsoleteProperties;
}

@property (nonatomic, assign)			CRScene*			rootScene;	// root scene, can be nil
@property (nonatomic, assign, readonly)	CRSceneItemBase*	superItem;	// root item in the scene
@property (nonatomic, readonly)			NSArray*			subItems;	// sub-items
@property (nonatomic, readonly)			CRPortsManager*		ports;		// ports
@property (nonatomic, strong)			id					tag;		// just a tag

@property (nonatomic, readonly)			BOOL				isLoaded;	// signals whether reading the object from data is complete

// The idea:
// Complex loading/copying must be performed next way:
//  1. Init permanents (non-copy, non-coding) members
//  2. Decode members and subparams
//  3. Initialize coding-supported values with != nil check to construct objects missed in source
// No achive this goal we have two 'complete' methods designed to construct coding-depended and
// non-coding-depended values
- (id)init;
- (id)initNoDeferred;
- (id)initClean;
- (void)completeImmediateMembers;
- (void)completeDeferredMembers;

// Special
- (BOOL)acceptsSceneItem:(id)item;
- (BOOL)applySceneItem:(id)item;

// Ports
- (void)buildPorts;
- (void)connect;
- (void)disconnect;

- (void)subItem:(CRSceneItemBase *)processor portIsDirty:(CRSceneItemPort *)port;	// notifies item that some sub-item port is dirty
- (void)scene:(CRScene *)scene portIsDirty:(CRSceneItemPort *)port;					// notifies item that some scene port is dirty

- (BOOL)hasPort:(NSString *)portName;
- (CRSceneItemPort *)portNamed:(NSString *)portName;
- (void)restrictUsage:(NSUInteger)usage forPortNamed:(NSString *)portName;
- (void)linkPort:(NSString *)portName toPort:(CRSceneItemPort *)port;
- (void)breakLink:(NSString *)portName;

- (id)valueForPort:(NSString *)portName;
- (void)setValue:(id)value forPort:(NSString *)portName;
- (void)setValueSilently:(id)value forPort:(NSString *)portName;
- (BOOL)boolForPort:(NSString *)portName;
- (void)setBool:(BOOL)value forPort:(NSString *)portName;
- (NSInteger)integerForPort:(NSString *)portName;
- (void)setInteger:(NSInteger)value forPort:(NSString *)portName;
- (CGFloat)floatForPort:(NSString *)portName;
- (void)setFloat:(CGFloat)value forPort:(NSString *)portName;
- (NSRect)rectForPort:(NSString *)portName;
- (void)setRect:(NSRect)value forPort:(NSString *)portName;
- (CIImage *)imageForPort:(NSString *)portName;
- (void)setImage:(CIImage *)value forPort:(NSString *)portName;

// Chaining
- (void)chainSubItem:(CRSceneItemBase *)item toRoot:(CRSceneItemBase *)otherItem withPort:(NSString *)portName subsetID:(NSString *)subsetID intoList:(NSMutableArray *)list;
- (NSArray *)chainingDataForRoot:(CRSceneItemBase *)otherItem subsetID:(NSString *)subsetID;
- (void)chainToItem:(CRSceneItemBase *)otherItem subsetID:(NSString *)subsetID fetchValues:(BOOL)immediateFetch;
- (void)unchain;

// Obsolete properties
- (id)objectForObsoleteKey:(NSString *)key;
- (void)dropObjectForObsoleteKey:(NSString *)key;

// CRUndoable
- (NSArray *)paramsDescriptors;	// translate all data to ports
- (NSArray *)dependedUndoables;
- (void)safeSetValue:(id)value forKeyPath:(NSString *)keyPath;

// NSCoding
- (NSString *)embeddedKeyPath:(NSString *)originalKeyPath;
- (NSUInteger)codingVersion;
- (NSMutableDictionary *)deprecatedMapping;
- (void)decodeDeprecated:(NSCoder *)aDecoder;

// CREmbeddedResourcesContainer
- (BOOL)containsDataForKeyPath:(NSString *)keyPath;
- (id)dataForKeyPath:(NSString *)keyPath;
- (void)setData:(id)data forKeyPath:(NSString *)keyPath;

//////////////////////////////////////////////////////////////////////
#pragma mark Sub-items

- (CRSceneItemBase *)superItem;
- (BOOL)addSubItem:(CRSceneItemBase *)subItem;
- (BOOL)addSubItems:(NSArray *)itemsArray;
- (void)removeSubItem:(CRSceneItemBase *)subItem;
- (void)removeSubItems:(NSArray *)itemsArray;
- (void)removeAllSubItems;
- (void)removeFromSuperItem;

- (void)willAttachToSuperItem;
- (void)didAttachToSuperItem;
- (void)willDetachFromSuperItem;
- (void)didDetachFromSuperItem;

@end