/*******************************************************************************
 Copyright (c) 2005-2006 Jordy Rose
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 
 Except as contained in this notice, the name(s) of the above copyright holders
 shall not be used in advertising or otherwise to promote the sale, use or other
 dealings in this Software without prior authorization.
*******************************************************************************/

//
//  DockyardPreferences.h
//  Dockyard
//
#import <Foundation/Foundation.h>
#import "NSArray+CocoaDevUsersAdditions.h"
#import "NSArray+PantherIndexSetSupport.h"
#import "NSDictionary+NSArray+PlistMutableCopy.h"

#define DockyardItemSet ComBelkadanDockyard_ItemSet
#define DockyardDockAppSet ComBelkadanDockyard_DockAppSet
#define DockyardDockItemSet ComBelkadanDockyard_DockItemSet
#define DockyardWidgetSet ComBelkadanDockyard_WidgetSet
#define DockyardUnknownSet ComBelkadanDockyard_UnknownSet
/*!
 * @enum DockyardItemSet
 * @discussion Used to identify which items in a dock should be accessed.
 * @constant DockyardUnknownSet Used as a placeholder for a non-existent
 * or unknown set.
 * @constant DockyardDockAppSet Represents the applications in the dock
 * (the permanent items left of the divider).
 * @constant DockyardDockItemSet Represents the other, non-application items
 * in the dock (the permanent items right of the divider).
 * @constant DockyardWidgetSet Represents the active widgets in the Dashboard.
 */
enum DockyardItemSet {
	DockyardUnknownSet = 0,
	DockyardDockAppSet,
	DockyardDockItemSet,
	DockyardWidgetSet
};

#define DockyardPreferences ComBelkadanDockyard_Preferences 

@interface DockyardPreferences : NSObject {
	NSDistributedNotificationCenter *noteCenter;
	NSUserDefaults *defaults;
	NSMutableDictionary *defaultsDict; // Used to avoid create/delete/create/delete ad nauseum
	
	NSMutableDictionary *docks;
	NSMutableDictionary *dashboards;
	NSMutableArray *names;
	NSString *currentDock;
	BOOL shouldSwitchDashboard;
	
	NSString *identifier;
	id delegate;
}
- (id)initWithIdentifier:(NSString *)givenID;
- (void)update;

- (id)delegate;
- (void)setDelegate:(id)newDelegate;
- (id)defaultsValueForKey:(NSString *)key;
- (void)setDefaultsValue:(id)value forKey:(NSString *)key;

- (NSArray *)dockNames;
- (void)setDockNames:(NSArray *)newNames;
- (BOOL)shouldSwitchDashboard;
- (void)setShouldSwitchDashboard:(BOOL)shouldSwitchDashboard;
- (NSString *)currentDock;
- (unsigned)numberOfDocks;

- (NSDictionary *)dataForDocks;
- (NSDictionary *)dashboardDataForDocks;
- (NSDictionary *)dataForDockWithName:(NSString *)name;
- (NSDictionary *)dashboardDataForDockWithName:(NSString *)name;

- (int)moveItemAtIndex:(unsigned)sourceIndex toIndex:(unsigned)destIndex inSet:(enum DockyardItemSet)whichItems ofDock:(NSString *)name; 
- (int)moveItemsAtIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)destIndex inSet:(enum DockyardItemSet)whichItems ofDock:(NSString *)name;
- (BOOL)addItem:(NSString *)path toSet:(enum DockyardItemSet)itemSet ofDock:(NSString *)dockName;
- (BOOL)addURL:(NSURL *)url withLabel:(NSString *)label toDock:(NSString *)dockName;
- (BOOL)addItemWithData:(NSDictionary *)data toSet:(enum DockyardItemSet)itemSet ofDock:(NSString *)dockName;
- (BOOL)addItemsWithData:(NSArray *)data toSet:(enum DockyardItemSet)itemSet ofDock:(NSString *)dockName;
- (void)removeItemAtIndex:(unsigned)index fromSet:(enum DockyardItemSet)itemSet ofDock:(NSString *)dockName;
- (void)removeItemsAtIndexes:(NSIndexSet *)indexSet fromSet:(enum DockyardItemSet)itemSet ofDock:(NSString *)dockName;
- (NSArray *)itemsInSet:(enum DockyardItemSet)itemSet ofDock:(NSString *)dockName;
- (void)setItems:(NSArray *)dockItems inSet:(enum DockyardItemSet)itemSet ofDock:(NSString *)dockName;

- (BOOL)createDockWithName:(NSString *)name fromFile:(NSString *)path dashboardFile:(NSString *)dashboardPath;
- (BOOL)createDockWithName:(NSString *)name data:(NSDictionary *)dockData dashboardData:(NSDictionary *)dashboardData;
- (BOOL)createDocksWithNames:(NSArray *)dockNames data:(NSArray *)dockData dashboardData:(NSArray *)dashboardData;
- (BOOL)renameDock:(NSString *)oldName to:(NSString *)newName;
- (BOOL)rearrange;
- (BOOL)deleteDockWithName:(NSString *)name;
- (BOOL)deleteDockAtIndex:(unsigned)index;
- (BOOL)deleteDocksAtIndexes:(NSIndexSet *)indexSet;
- (BOOL)changeDock:(NSString *)newDock;
@end

/*!
 * @protocol DockyardPreferences_Delegate
 * @abstract Receives notifications from DockyardPreferences whenever something is changed.
 * @discussion This informal protocol receives notifications from DockyardPreferences when
 * something is changed. Although any object can register for these notifications, the delegate
 * of DockyardPreferences is guaranteed that the DockyardPreferences object will have updated
 * itself before the delegate receives any of these messages.
 */
@interface NSObject (ComBelkadanDockyard_PreferencesNotifications)
/*!
 * Informs the delegate (and any other listeners) that the Dockyard global defaults have changed. This
 * is largely used for internal synchronization purposes, and is not usually needed. The notification
 * is DockyardDefaultsChangedNotification, and is unique because its object is the key changed, instead
 * of the identifier of the preferences object where the change originated. This allows you to register
 * for specific defaults changes, instead of getting the global change all the time. The notification's
 * <code>userInfo</code> dictionary contains the key and the value set, under the keys &#64;"key" and
 * &#64;"value". If the value is <code>&#64;""</code>, check if the &#64;"isNil" key exists. If it does,
 * the defaults value has been cleared instead of set.
 *
 * @functiongroup Changing Dockyard settings
 */
- (void)dockyardDefaultsChanged:(NSNotification *)note;
/*!
 * Informs the delegate (and any other listeners) that Dashboard switching has been enabled or disabled.
 * The notification is DockyardDashboardSwitchChangedNotification, and its object is the identifier of
 * the preferences object where the change originated. The <code>userInfo</code> dictionary contains one
 * key, &#64;"shouldSwitchDashboard", which contains <code>YES</code> if Dashboard switching has been enabled,
 * and <code>NO</code> if it has been disabled.
 */
- (void)dockyardDashboardSwitchChanged:(NSNotification *)note;
/*!
 * Informs the delegate (and any other listeners) that the items of a dock have changed.
 * The notification is DockyardDockItemsChangedNotification, and the object is the identifier
 * of the preferences object where the change originated. The <code>userInfo</code> dictionary
 * contains three objects: &#64;"dockName", which is the name of the dock that was changed;
 * &#64;"whichItems", which is the set that was modified, in NSNumber format; and &#64;"newItems",
 * the NSArray containing the new items, in the same format as itemsInSet:ofDock:.
 *
 * @functiongroup Changing a dock's contents
 */
- (void)dockyardDockItemsChanged:(NSNotification *)note;
/*!
 * Informs the delegate (and any other listeners) that the dock has been changed. The notification
 * is DockyardDockChangedNotification and the object is the identifier of the preferences object
 * where the change originated. The <code>userInfo</code> dictionary contains four objects:
 * &#64;"newDock", which is the name of the dock that has been switched in; &#64;"oldDock", which is the
 * name of the dock that was switched out; and &#64;"oldDockData" and &#64;"oldDashboardData", which are
 * updated version of the previous dock's data.
 *
 * @functiongroup Switching to a new dock
 */
- (void)dockyardDockChanged:(NSNotification *)note;
/*!
 * Informs the delegate (and any other listeners) that a new dock has been created. The notification
 * is DockyardDockCreatedNotification and the object is the identifier of the preferences object
 * where the change originated. The <code>userInfo</code> dictionary contains three objects:
 * &#64;"name", which is the name of the new dock; and &#64;"dockData" and &#64;"dashboardData", which
 * contain the new dock's data (in defaults formats).
 *
 * @functiongroup Creating, deleting, or modifying docks
 */
- (void)dockyardDockCreated:(NSNotification *)note;
/*!
 * Informs the delegate (and any other listeners) that a dock has been renamed. The notification
 * is DockyardDockRenamedNotification and the object is the identifier of the preferences object
 * where the change originated. The <code>userInfo</code> dictionary contains two objects:
 * &#64;"oldName", which is the old name of the dock; and &#64;"newName", which is the new name
 * of the dock.
 */
- (void)dockyardDockRenamed:(NSNotification *)note;
/*!
 * Informs the delegate (and any other listeners) that the docks have been reordered. The notification
 * is DockyardDocksReorderedNotification and the object is the identifier of the preferences object
 * where the change originated. The <code>userInfo</code> dictionary contains one object,
 * &#64;"dockNames", which contains the list of dock names in their new order.
 */
- (void)dockyardDocksReordered:(NSNotification *)note;
/*!
 * Informs the delegate (and any other listeners) that a dock has been deleted. The notification
 * is DockyardDockDeletedNotification and the object is the identifier of the preferences object
 * where the change originated. The <code>userInfo</code> dictionary contains one object,
 * &#64;"name", which contains the name of the deleted dock. Note that if multiple docks are deleted,
 * the delegate will receive the <code>dockyardDocksDeleted:</code> message instead.
 *
 * @see #dockyardDocksDeleted:
 */
- (void)dockyardDockDeleted:(NSNotification *)note;
/*!
 * Informs the delegate (and any other listeners) that multiple docks have been deleted. The
 * notification is DockyardDocksDeletedNotification and the object is the identifier of the
 * preferences object where the change originated. The <code>userInfo</code> dictionary contains
 * two objects: &#64;"firstName", which contains the name of the first deleted dock (for testing
 * purposes); and &#64;"indexSet", which contains the indexes of the deleted docks as an archived
 * NSIndexSet. Note that if only one dock is deleted, the delegate will receive the
 * <code>dockyardDockDeleted:</code> message instead.
 *
 * @see #dockyardDockDeleted:
 */
- (void)dockyardDocksDeleted:(NSNotification *)note;
@end

#define DockyardDockChangedNotification	ComBelkadanDockyard_DockChangedNotification
#define DockyardDockCreatedNotification ComBelkadanDockyard_DockCreatedNotification
#define DockyardDockRenamedNotification ComBelkadanDockyard_DockRenamedNotification
#define DockyardDocksReorderedNotification ComBelkadanDockyard_DocksReorderedNotification
#define DockyardDockDeletedNotification ComBelkadanDockyard_DockDeletedNotification
#define DockyardDocksDeletedNotification ComBelkadanDockyard_DocksDeletedNotification
#define DockyardDashboardSwitchChangedNotification ComBelkadanDockyard_DashboardSwitchChangedNotification
#define DockyardDefaultsChangedNotification ComBelkadanDockyard_DefaultsModifiedNotification
#define DockyardDockItemsChangedNotification ComBelkadanDockyard_DockItemsChangedNotification
/*!
 * Posted whenever the user changes docks.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDockChanged:
 */
extern NSString * const DockyardDockChangedNotification;
/*!
 * Posted whenever the user creates a new dock.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDockCreated:
 */
extern NSString * const DockyardDockCreatedNotification;
/*!
 * Posted whenever the user renames a dock.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDockRenamed:
 */
extern NSString * const DockyardDockRenamedNotification;
/*!
 * Posted whenever the user rearranges their docks.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDocksReordered:
 */
extern NSString * const DockyardDocksReorderedNotification;
/*!
 * Posted whenever the user deletes a dock.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDockDeleted:
 * @see DockyardDocksDeletedNotification
 */
extern NSString * const DockyardDockDeletedNotification;
/*!
 * Posted whenever the user deletes multiple docks.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDocksDeleted:
 */
extern NSString * const DockyardDocksDeletedNotification;
/*!
 * Posted whenever the user enables or disables dashboard switching.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDashboardSwitchChanged:
 */
extern NSString * const DockyardDashboardSwitchChangedNotification;
/*!
 * Posted whenever the user sets or clears a key in the dashboard defaults.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDefaultsChanged:
 */
extern NSString * const DockyardDefaultsChangedNotification;
/*!
 * Posted whenever the user changes the items in a dock.
 * @see NSObject+ComBelkadanDockyard_PreferencesNotifications#dockyardDockItemsChanged:
 */
extern NSString * const DockyardDockItemsChangedNotification;
