/*
**  CWIMAPCacheManager.m
**
**  Copyright (c) 2001-2005
**
**  Author: Ludovic Marcotte <ludovic@Sophos.ca>
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**  
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**  Lesser General Public License for more details.
**  
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <Pantomime/CWIMAPCacheManager.h>

#include <Pantomime/CWConstants.h>
#include <Pantomime/CWIMAPMessage.h>

#include <Foundation/NSArchiver.h>
#include <Foundation/NSException.h>
#include <Foundation/NSValue.h>

static int currentIMAPCacheManagerVersion = 3;

//
//
//
@implementation CWIMAPCacheManager

- (id) initWithPath: (NSString *) thePath
{
  self = [super initWithPath: thePath];
  
  [CWIMAPCacheManager setVersion: currentIMAPCacheManagerVersion];
  _table = NSCreateMapTable(NSIntMapKeyCallBacks, NSObjectMapValueCallBacks, 128);
  _UIDValidity = 0;

  return self;
}


//
//
//
- (void) dealloc
{
  NSFreeMapTable(_table);
  [super dealloc];
}


//
// NSCoding protocol
//
- (void) encodeWithCoder: (NSCoder *) theCoder
{
  [CWIMAPCacheManager setVersion: currentIMAPCacheManagerVersion];
  [theCoder encodeObject: [NSNumber numberWithUnsignedInt: _UIDValidity]];
  [theCoder encodeObject: _cache];
}


//
//
//
- (id) initWithCoder: (NSCoder *) theCoder
{
  int version;
  
  version = [theCoder versionForClassName: NSStringFromClass([self class])];
  
  self = [super initWithPath: nil];

  _table = NSCreateMapTable(NSIntMapKeyCallBacks, NSObjectMapValueCallBacks, 128);

  if (version < currentIMAPCacheManagerVersion)
    {
      // We do nothing, so the cache will be entirely reloaded
      [NSException raise: NSInternalInconsistencyException  format: @"IMAP cache error."];
    }
  else
    {
      _UIDValidity = [[theCoder decodeObject] unsignedIntValue];
      [self setCache: [theCoder decodeObject]];
    }

  return self;
}


//
//
//
- (void) addObject: (id) theObject
{
  NSMapInsert(_table, (void *)[theObject UID], theObject);
  [super addObject: theObject];
}


//
//
//
- (void) removeObject: (id) theObject
{
  NSMapRemove(_table, (void *)[theObject UID]);
  [super removeObject: theObject];
}


//
//
//
- (CWIMAPMessage *) messageWithUID: (unsigned int) theUID
{
  return NSMapGet(_table, (void *)theUID);
}


//
//
//
- (void) setCache: (NSArray *) theCache
{
  int i, count;
  id o;

  [super setCache: theCache];
  
  // We populate our map table
  count = [_cache count];
  
  for (i = 0; i < count; i++)
    {
      o = [_cache objectAtIndex: i];
      NSMapInsert(_table, (void *)[o UID], o);
    }
}


//
//
//
- (unsigned int) UIDValidity
{
  return _UIDValidity;
}

//
//
//
- (void) setUIDValidity: (unsigned int) theUIDValidity
{
  _UIDValidity = theUIDValidity;
}


//
//
//
- (void) invalidate
{
  NSLog(@"IMAPCacheManager - flushing the cache...");
  [super invalidate];
  _UIDValidity = 0;
  [self synchronize];
}


//
//
//
+ (id) cacheWithPath: (NSString *) thePath
{
  id o;

  o = [super cacheWithPath: thePath];

  if (!o)
    {
      o = AUTORELEASE([[CWIMAPCacheManager alloc] initWithPath: thePath]);
    }

  return o;
}
@end
