//
//  ASWFileRef.h
//  WireTapPro2
//
//  Created by Dominic Feira on 10/19/05.
//  Copyright 2005-2008 Ambrosia Software Inc. All rights reserved.
//

/*! \file ASWFileRef.h
	This is a wrapper around FSRef that makes it "cocoa-like".
	The goal is to avoid using paths everywhere (which can go stale quickly).	
*/

#if !defined(ASW_NOT_IPHONE)
#define ASW_NOT_IPHONE !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
#endif

#if ASW_NOT_IPHONE
#import <Cocoa/Cocoa.h>
#endif
/*! 
	A wrapper around FSRef to reference files without using paths, which can break. 
	The iPhone version uses NSURL.  
 */
@interface ASWFileRef : NSObject <NSCoding, NSCopying, NSLocking>

{
#if ASW_NOT_IPHONE
	Boolean mWasAliased;
	FSRef mAliasRef;
	FSRef mFileRef;
#endif
	
	NSURL* mURL;
	BOOL mHashSet;
	UInt32 mHash;
	NSLock* mLock;
	id mDelegate;
}

/*! Creates an autoreleased ASWFileRef with the supplied path. Any aliases are resolved.
    \param path A valid path on the filesystem. It doesn't have to be expanded.
    \param errorOut Contains an NSError if an error occcurs. Can pass in nil.
    \result nil if an error occurs.
 */
+ (id) fileRefWithPath: (NSString*) path error: (NSError**) errorOut;


#if ASW_NOT_IPHONE

/*! Creates an autoreleased ASWFileRef with the supplied path.
 \param path A valid path on the filesystem. It doesn't have to be expanded.
 \param resolve Wether or not aliases should be resolved.
 \param errorOut Contains an NSError if an error occcurs. Can pass in nil.
 \result nil if an error occurs.
 */
+ (id) fileRefWithPath: (NSString*) path resolveAlias: (BOOL) resolve error: (NSError**) errorOut;

/*! Inializes an ASWFileRef with the supplied FSRef.  Any aliases are resolved.
    \param fileRef A valid fsRef on the filesystem.
    \param errorOut Contains an NSError if an error occcurs.
    \result nil if an error occurs.
 */
+ (id) fileRefWithFSRef: (FSRef) fileRef error: (NSError**) errorOut;

/*! Initializes an ASWFileRef with the supplied FSRef.
	\param fileRef A valid fsRef on the filesystem.
	\param resolve Wether or not aliases should be resolved.
	\param errorOut Contains an NSError if an error occcurs. Can pass in nil.
	\result nil if an error occurs.
	 */
+ (id) fileRefWithFSRef: (FSRef) fileRef resolveAlias: (BOOL) resolve error: (NSError**) errorOut;
#endif

+ (id) fileRefWithURL: (NSURL*) url error: (NSError**) errorOut;

/*! Creates an autoreleased ASWFileRef with the supplied path.
	\param path A valid path on the filesystem. It doesn't have to be expanded.
	\param resolve Wether or not aliases should be resolved.
	\param errorOut Contains an NSError if an error occcurs. Can pass in nil.
	\result nil if an error occurs.
*/
- (id) initWithPath: (NSString*) path resolveAlias: (BOOL) resolve error: (NSError**) errorOut;

#if ASW_NOT_IPHONE
/*! Initializes an ASWFileRef with the supplied FSRef.
	 \param fileRef A valid fsRef on the filesystem.
	 \param resolve Wether or not aliases should be resolved.
	 \param errorOut Contains an NSError if an error occcurs. Can pass in nil.
	 \result nil if an error occurs.
*/
- (id) initWithFSRef: (FSRef) fileRef resolveAlias: (BOOL) resolve error: (NSError**) errorOut;



/*! Initializes an ASWFileRef with the supplied FSRef.
 The FSRef is not held onto in anyway.  It can be destroyed at anytime after initing.
 \param path A valid path on the filesystem. It doesn't have to be expanded.
 \param errorOut Contains an NSError if an error occcurs. Can pass in nil.
 \result Nil if an error occurs.
 */
- (id) initWithFSRef: (FSRef) fileRef error: (NSError**) errorOut;
#endif

/*! Initializes an ASWFileRef with the supplied path.
 \param path A valid path on the filesystem. It doesn't have to be expanded.
 \param errorOut Contains an NSError if an error occcurs. Can pass in nil.
 \result Nil if an error occurs.
 */
- (id) initWithPath: (NSString*) path error: (NSError**) errorOut;



/*! Initializes an ASWFileRef with the supplied url.
 \param path A valid file url on the filesystem.
 \param errorOut Contains an NSError if an error occcurs. Can pass in nil.
 \result Nil if an error occurs.
 */
- (id) initWithURL: (NSURL*) url error: (NSError**) errorOut;

/*! Gets a NSString path.
    \result Nil if an error occurs.
 */
- (NSString*) path;

/*!
	Returns true if the file still exists.
 */
- (BOOL) fileExists;

/*! Gets a url referencing the file.
 \result Nil if an error occurs.
 */
- (NSURL*) url;

/*! \param desiredName Desired name
	\result success or failure
*/
- (BOOL) renameWithName: (NSString*) desiredName error: (NSError**) errorOut;

/*! Gets the file name for this file or directory
    \result Nil if an error occurs
*/
- (NSString*) name;

/*! Gets the name minus the path extension
 \result Nil if an error occurs
 */
- (NSString*) baseName;

/*! \brief The path extension of the file */
- (NSString*) pathExtension;

/*! Gets the display name for this file or directory
    \result Nil if an error occurs
*/
- (NSString*) displayName;

/*! Returns TRUE if ASWFileRef refers to a directory */
- (BOOL) isDirectory;

/*! Returns true if self is a descendent of fileRef. */
- (BOOL) isDescendentOf: (ASWFileRef*) fileRef;

/*! Returns true if self is a child of fileRef. */
- (BOOL) isChildOf: (ASWFileRef*) fileRef;

/*! Returns the parent directory.  nil if self doesn't refer to a directory or if self is root */
- (ASWFileRef*) parent;

/*! Returns the file contained within a directory, or nil if self doesn't refer to a directory */
- (NSArray*) childrenError: (NSError**) errorOut;

#if ASW_NOT_IPHONE
/*! Returns an enumerator...if you are just going to enumerate over the children, use this. It's faster. */
- (NSEnumerator*) childEnumerator;
#endif

/*! Returns true if fileRef is a descendent of self. */
- (BOOL) isParentOf: (ASWFileRef*) fileRef;

/*! Returns an ASWFileRef for the child with name, if it exists.
	\param name The name of the child to get.
	\result the found child.  nil if a child with the given name doesn't exist.
*/
- (ASWFileRef*) childWithName: (NSString*) name error: (NSError**) error;

/*! Create a child with the given name.
	\param name The name of the child to create.
	\param directory TRUE if the child created should be a directory.
	\result the newly created child.
*/
- (ASWFileRef*) createChildWithName: (NSString*) name asDirectory: (BOOL) directory error: (NSError**) error;

/*! Create a child with name if it doesn't already exist.  Otherwise just get the reference to the child.
	\param name The name of the child to create.
	\param directory TRUE if the child created should be a directory.
	\result the child referred to by name
*/
- (ASWFileRef*) createChildIfNeededWithName: (NSString*) name asDirectory: (BOOL) directory error: (NSError**) error;

#if ASW_NOT_IPHONE
/*! The FSRef that represents this file.  Use this with Carbon routines when necessary.
	 \result The underlying FSRef.
*/
- (FSRef*) fsRef;

/*! An ASWFileRef to the alias that created this fileRef, if it was created with an alias.
	\result ASWFileRef to the alias.
*/
- (ASWFileRef*) aliasFileRef;
#endif


/*! Returns the cocoa file attributes for this file.*/
- (NSDictionary*) attributes;

/*! Sets the cocoa file attributes for this file. */
- (void) setAttributes: (NSDictionary*) dict;

#if ASW_NOT_IPHONE
/*! Returns the Finder file info for this file.*/
- (FileInfo) fileInfo;

/*! Sets the Finder file info for this file. */
- (OSStatus) setFileInfo: (FileInfo) info;


/*! Returns the icon for this file. */
- (NSImage*) icon;

#endif

/*! returns whether the two objects are equal, calls through to isEqualTo: */
- (BOOL) isEqual: (id) rhs;

/*! returns whether the two objects are equal */
- (BOOL) isEqualTo: (id) rhs;

/*! compares the two objects and returns an NSComparisonResult */
- (NSComparisonResult) compare: (ASWFileRef*) fileRef;

/*! returns a hash based on the file's NSFileSystemNumber */
- (unsigned) hash;

#if ASW_NOT_IPHONE
/*! returns whether the receiver is an alias */
- (BOOL) isAlias;

/*! is the receiver in the Trash */
- (BOOL) isInTrash;
#endif
@end

#if ASW_NOT_IPHONE
/* compatibility layer - These are deprecated.*/
@interface ASWFileRef (ASWFileRefDeprecated)
- (NSArray*) children  __attribute__((deprecated));
- (ASWFileRef*) childWithName: (NSString*) name  __attribute__((deprecated));
- (ASWFileRef*) createChildWithName: (NSString*) name asDirectory: (BOOL) directory  __attribute__((deprecated));
- (ASWFileRef*) createChildIfNeededWithName: (NSString*) name asDirectory: (BOOL) directory  __attribute__((deprecated));
- (BOOL) renameWithName: (NSString*) desiredName  __attribute__((deprecated));

/*! On the rare occasion that access to an FSSpec is needed, use this method.
 \param specOut the FSSpec to be filled out.
 \result file system error code.
 */
- (OSStatus) getFSSpec: (FSSpec*) specOut __attribute__((deprecated));

/*! Get data that represents an alias to the file referenced by this ASWFileRef.
 \result NSData containing the alias.
 \discussion If you need to save a reference to a file, just encode the entire ASWFileRef as it is much more future proof.
 */
- (NSData*) aliasData __attribute__((deprecated));

/*! Initializes an ASWFileRef with the supplied NSData that contains an alias.
 \param data NSData that contains alias data.
 \param errorOut Contains an NSError if an error occcurs. Can pass in nil.
 \result nil if an error occurs.
 */
- (id) initWithAliasData: (NSData*) data error: (NSError**) errorOut __attribute__((deprecated));

/*! Initializes an ASWFileRef with the supplied NSData that contains an alias.
 \param data NSData that contains alias data.
 \param errorOut Contains an NSError if an error occcurs. Can pass in nil.
 \result nil if an error occurs.
 */
+ (id) fileRefWithAliasData: (NSData*) data error: (NSError**) errorOut __attribute__((deprecated));
@end
#endif
