//
//  ASWDocumentBundle.h
//  ASWAppKit
//
//  Created by dominic on 9/24/08.
//  Copyright 2008 Ambrosia Software, Inc.. All rights reserved.
//

/*! \file ASWDocumentBundle.h
 */

extern NSString* ASWMediaDocumentBundle_ThumbnailAuto;
extern NSString* ASWMediaDocumentBundle_ThumbnailJPEG;
extern NSString* ASWMediaDocumentBundle_ThumbnailPNG;

extern NSString* ASWDocumentBundle_DocumentDomain;
#import "ASWFileRef.h"

/*! \brief ASWDocumentBundle
	Manages the on storage representation of a document.
 
	All setters/getters that take a domain argument allow for save information to be split up into different domains.  
	A nil domain indicates the document domain.
	Setters/getters that do not take a domain work only with the document domain.  
	They are merely convenience methods that call the corresponding setter/getter with a domain of ASWDocumentBundle_DocumentDomain.
 
	Any other domains should be specified with a proper reverse URI, such as com.ambrosiasw.library.cache.
 
 */

/*! class ASWDocumentBundle
	ASWDocumentBundle is an interface to a bundle.  
	It manages the on disk representation of that bundle.  
	ASWDocumentBundle is also a contract between the document format on disk and an applicaiton.
	It is important that if ASWDocumentBundle is subclassed that the method that is overridden 
	always calls super to handle the on disk representation.
	It is also ok to subclass ASWDocumentBundle to add type abstractions.  One example
	would be a thumbnail property.
 */

@interface ASWDocumentBundle : NSObject 
{
	ASWFileRef* mFileRef;
	UInt32 mCreatorCode;
	UInt32 mTypeCode;
	BOOL mPackageInfoLoaded;
	BOOL mLoadingPkgInfo;
}

+ (id) documentBundleWithURL: (NSURL*) url create: (BOOL) create error: (NSError**) error;
+ (id) documentBundleWithPath: (NSString*) path create: (BOOL) create error: (NSError**) error;
+ (id) documentBundleWithFileRef: (ASWFileRef*) fileRef error: (NSError**) error;


/*!
 \param url URL to load the bundle from
 \param create Wether or not to create the bundle if it doesn't exist.
 \return nil if bundle doesn't exist at url, after the create operation if one is specified */
- (id) initWithURL: (NSURL*) url 
			create: (BOOL) create 
			 error: (NSError**) error;

/*!
 \param path Path to load the bundle from
 \param create Wether or not to create the bundle if it doesn't exist.
 \return nil if bundle doesn't exist at path, after the create operation if one is specified */
- (id) initWithPath: (NSString*) path 
			 create: (BOOL) create 
			  error: (NSError**) error;

/*! \brief Designated initializer
 \param path Fileref to load the bundle from
 */
- (id) initWithFileRef: (ASWFileRef*) fileRef error: (NSError**) error;

/*!	\return URL of the bundle */
- (NSURL*) url;

/*!	\return Path of the bundle */
- (NSString*) path;

/* \return File reference to the bundle */
- (ASWFileRef*) fileRef;

/*!	\brief Set the bundle creator code.  This is stored in the PkgInfo file inside of the bundle. */
- (void) setCreatorCode: (UInt32) code;

/*!	\return Bundle creator code */
- (UInt32) creatorCode;

/*!	\brief Set the bundle type code.  This is stored in the PkgInfo file inside of the bundle. */
- (void) setTypeCode: (UInt32) code;

/*!	\return Bundle type code */
- (UInt32) typeCode;

/*! \brief Set the document dictionary. Dictionary must be serializable as a plist.
	\param dict The dictionary to set.  The previous dictionary will be overwritten.
 */
- (BOOL) setDictionary: (NSDictionary*) dict 
				 error: (NSError**) error;

/*!	\brief Get the document dictionary. */
- (NSDictionary*) dictionaryError: (NSError**) error;

/*! \brief Encode a document object to disk 
 	\param object The object to encode.  It must implement the NSCoding protocol. 
 	\param key They key to store the object under.
 */
- (BOOL) saveObject: (id <NSCoding>) object 
			withKey: (NSString*) key 
			  error: (NSError**) error;

/*	\brief Decode an object from the Document domain. */
- (id) decodeObjectWithKey: (NSString*) key 
					 error: (NSError**) error;

/*!	\brief Decode an object, as above, with a delegate. 
	\param key The name of the object.
	\param keyedUnarchiverDelegate The delegate for the unarchiver. See NSKeyedUnarchiverDelegate.
	\param error The error to return.
	\return The decoded object.
 */
- (id) decodeObjectWithKey: (NSString *) key 
				  delegate: (id) keyedUnarchiverDelegate /* on 10.6+ could be id<NSKeyedUnarchiverDelegate> */
					 error: (NSError **) error;


/*	\brief Returns the url for a file in the Document domain 
 	\param name The name of the resource.
	\param type The type of the document.  This can be nil.
	\param directoryPath The relative directory path that the resource is in.
	\param create Create the directory path if it doesn't exist yet.
 */
- (NSURL*) urlForResource: (NSString*) name 
				   ofType: (NSString*) type 
			  inDirectory: (NSString*) directoryPath 
		  createDirectory: (BOOL) create 
					error: (NSError**) error;

/*	\brief Copy a file into the bundle.
 \param resource Then URL of the resource to copy into the bundle.
 \param directoryPath The relative directory path that the resource is in.
 \param newName Optionally rename the resource in the bundle.
 */
- (BOOL) copyResource: (NSURL*) resource 
		  toDirectory: (NSString*) directoryPath
			   rename: (NSString*) newName
				error: (NSError**) errorOut;

/*	\brief Move a file into the bundle.
 \param resource Then URL of the resource to copy into the bundle.
 \param directoryPath The relative directory path that the resource is in.
 \param newName Optionally rename the resource in the bundle.
 */
- (BOOL) moveResource: (NSURL*) resource 
		  toDirectory: (NSString*) directoryName
			   rename: (NSString*) newName
				error: (NSError**) errorOut;

/*	\brief Remove a resource.  Empty directories are also removed.
	\param brief Remove the resource.
	\param type The type of the resource.
	\param directoryPath The relative path othe directory.
 */
- (BOOL) removeResource: (NSString*) name 
				 ofType: (NSString*) type 
			inDirectory: (NSString*) directoryPath 
				  error: (NSError**) error;

/* For accessing other special domains of information.  Do not store core document information in these domains */
// Use these sparingly.

/*	\brief Get the dictionary for a particular domain. 
	\param domain The domain to get the dictionary from.
 */
- (NSDictionary*) dictionaryForDomain: (NSString*) domain 
								error: (NSError**) error;

/*	\brief Set the dictionary for a particular domain.
	\param dict The dictionary to set.  The previous dictionary will be overwritten.  Must be a serializable plist.
	\param domain The domain to set the dictionary for.
 */
- (BOOL) setDictionary: (NSDictionary*) dict 
			 forDomain: (NSString*) domain 
				 error: (NSError**) error;

/*! \brief Encode an object to disk 
 \param object The object to encode.  It must implement the NSCoding protocol. 
 \param key They key to store the object under.
 \param domain The domain to save the object in.
 */
- (BOOL) saveObject: (id <NSCoding>) object 
			withKey: (NSString*) key 
			 domain: (NSString*) domain 
			  error: (NSError**) error;

/*!	\brief Decode an object from the Document domain. 
	\param key The key to retrieve the document.
	\param domain The domain to retieve the object from.
 */
- (id) decodeObjectWithKey: (NSString*) key 
					domain: (NSString*) domain 
					 error: (NSError**) error;


/*!	\brief Returns the url for a file in the Document domain 
 \param name The name of the resource.
 \param type The type of the document.  This can be nil.
 \param directoryName The directory that the resource is in.
 \param domain The domain to create get the URL for.
 \param create Create the directory path if it doesn't exist yet.
 */
- (NSURL*) urlForResource: (NSString*) name 
				   ofType: (NSString*) type 
			  inDirectory: (NSString*) directoryPath 
				   domain: (NSString*) domain 
		  createDirectory: (BOOL) create 
					error: (NSError**) error;

/*!	\brief Returns the url for a file in the Document domain 
 \param name The name of the resource.
 \param type The type of the document.  This can be nil.
 \param directoryName The directory that the resource is in.
 \param domain The domain to create get the URL for.
 \param create Create the directory path if it doesn't exist yet.
 */
/*- (NSURL*) urlsForResourceOfType: (NSString*) type 
					 inDirectory: (NSString*) directoryPath 
						  domain: (NSString*) domain 
						   error: (NSError**) error;*/

/*!	\brief Copies a resource into the bundle.
 \param resource The url to copy.
 \param directoryPath The relative destination path in the bundle.
 \param newName The name to rename the file with.
 \param domain The domain to copy the resource into.
 */
- (BOOL) copyResource: (NSURL*) resource 
		  toDirectory: (NSString*) directoryPath
			   rename: (NSString*) newName
			   domain: (NSString*) domain 
				error: (NSError**) errorOut;

/*!	\brief Moves a resource into the bundle.
 \param resource The url to copy.
 \param directoryPath The relative destination path in the bundle.
 \param newName The name to rename the file with.
 \param domain The domain to copy the resource into.
 */
- (BOOL) moveResource: (NSURL*) resource 
		  toDirectory: (NSString*) directoryName 
			   rename: (NSString*) newName
			   domain: (NSString*) domain 

				error: (NSError**) errorOut;

/*!	\brief Remove a resource.  Empty directories are also removed.
 \param type The type of the resource.
 \param directoryPath The relative path directory.
 \param domain The domain to remove the resource from.
 */
- (BOOL) removeResource: (NSString*) name 
				 ofType: (NSString*) type 
			inDirectory: (NSString*) directoryPath 
				 domain: (NSString*) domain 
				  error: (NSError**) error;

/*! \brief Returns an arry of the domains that are currently present in the bundle */
- (NSArray*) presentDomains: (NSError**) error;

/*! \brief Returns an arry of the resource types that are currently present in the specified domain */
- (NSArray*) resourceTypesInDomain: (NSString*) domain error: (NSError**) error;

/*! \brief Remove the specified domain 
 \return True if successful.*/
- (BOOL) removeDomain: (NSString*) domain error: (NSError**) error;

/*! \brief Remove all domains except the document domain.
 \return True if successful. */
- (BOOL) removeNonDocumentDomains: (NSError**) error;
	
@end
