/*
**  AttributesSource.m
**
**  Copyright (c) 2004
**
**  Author: Yen-Ju Chen <yjchenx@hotmail.com>
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation; either version 2 of the License, or
**  (at your option) any later version.
**
**  This program 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 General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <AppKit/AppKit.h>
#include "AttributesSource.h"
#include "LibrarySource.h"
#include "GNUstep.h"
#include "Constants.h"
#include "Utilities.h"
#include <AppKit/AppKit.h>

static AttributesSource *sharedInstance = nil;
static NSString *ItemAttributeKey = @"ItemAttributeKey";

@implementation AttributesSource
/* For newer format */
- (unsigned int) _reIndexUniqueNumber
{
  NSLog(@"_reindex Attributes");
  LibrarySource *library = [LibrarySource sharedSource];
  unsigned int i, icount = [self count];
  unsigned int j, jcount = [library count];
  unsigned int index, uid;
  NSString *title, *path;
  id object;
  for(i = 0; i < icount; i++)
    {
      title = [self titleAtIndex: i];
      for(j = 0; j < jcount; j++)
        {
	  path = [library pathOfItemAtIndex: j];
	  if ([title isEqualToString: path])
	    {
              uid = [library uniqueNumberAtIndex: j];
              [self setUniqueNumber: uid atIndex: i];
	    }
        }
    }
}


/* write methods */
- (void) setAttributes: (NSDictionary *) attr atIndex: (unsigned int) index
{
  [self setObject: attr atIndex: index forKey: ItemAttributeKey];
}

- (void) setAttribute: (id) attr atIndex: (unsigned int) index
                                  forKey: (id) key
{
  NSMutableDictionary *dict = [[self attributesAtIndex: index] mutableCopy];
  [dict setObject: AUTORELEASE([attr copy])
           forKey: AUTORELEASE([key copy])];
  [self setAttributes: dict atIndex: index];
}

- (void) removeAttributeAtIndex: (unsigned int) index forKey: (id) key
{
  NSMutableDictionary *dict = [[self attributesAtIndex: index] mutableCopy];
  [dict removeObjectForKey: key];
  [self setAttributes: dict atIndex: index];
}

/* read methods */
- (NSDictionary *) attributesAtIndex: (unsigned int) index
{ 
  return [self objectAtIndex: index forKey: ItemAttributeKey];
} 

- (id) attributeAtIndex: (unsigned int) index forKey: (NSString *) key
{
  return AUTORELEASE([[(NSDictionary *)[self objectAtIndex: index forKey: ItemAttributeKey] objectForKey: key] copy]);
} 

- (id) attributeAtIndex: (unsigned int) index forName: (NSString *) n
{
  NSDictionary *dict = [self attributesAtIndex: index];
  NSArray *allKeys = [dict allKeys];
  id key, name, value;
  unsigned int i, count = [allKeys count];
  for(i = 0; i < count; i++)
    {
      key = [allKeys objectAtIndex: i];
      name = nameOfAttributeKey(key);
      if ([name isEqualToString: n])
        return AUTORELEASE([[dict objectForKey: key] copy]);
    }
  return nil;
} 

- (NSSet *) namesOfAttributes
{
  unsigned int i, icount, j, jcount;
  id key;
  NSDictionary *dict;
  NSArray *allKeys;
  NSMutableSet *set = [[NSMutableSet alloc] init];

  icount = [self count];
  for(i = 0; i < icount; i++)
    {
      dict = [self attributesAtIndex: i];
      allKeys = [dict allKeys];
      jcount = [allKeys count];
      for(j = 0; j < jcount; j++)
        {
           key = nameOfAttributeKey([allKeys objectAtIndex: j]);
	   [set addObject: key];
	}
    }
  return AUTORELEASE(set);
}

- (NSSet *) keysOfAttributes
{
  unsigned int i, icount, j, jcount;
  id key;
  NSDictionary *dict;
  NSArray *allKeys;
  NSMutableSet *set = [[NSMutableSet alloc] init];

  icount = [self count];
  for(i = 0; i < icount; i++)
    {
      dict = [self attributesAtIndex: i];
      allKeys = [dict allKeys];
      jcount = [allKeys count];
      for(j = 0; j < jcount; j++)
        {
           key = [allKeys objectAtIndex: j];
	   [set addObject: AUTORELEASE([key copy])];
	}
    }
  return AUTORELEASE(set);
}

/* basic methods */

+ (AttributesSource *) sharedSource
{
  if (sharedInstance == nil)
    {
      sharedInstance = [[AttributesSource alloc] init];
    }
  return sharedInstance;
}


- (BOOL) loadSourceAtPath: (NSString *) path
{
  if ([super loadSourceAtPath: path] == NO) return NO;
  NSString *attributesPath = [self path];
  BOOL loadResult;
  loadResult = [self readFromFile: attributesPath];
  if (loadResult == YES) 
    {
      makeBackup(attributesPath);
      /* Check whether it is a new version */
      if (([self count] > 0) && ([self uniqueNumberAtIndex: 0] == NSNotFound))
        {
          [self _reIndexUniqueNumber];
        }

      return YES;
    }
  else
    {
      /* Check backup file */
      NSFileManager *fm = [NSFileManager defaultManager];
      BOOL isDir;
      NSString *backup = [attributesPath stringByAppendingString: @"~"];
      loadResult = [self readFromFile: backup];
      if (loadResult == YES)
        {
          int result = NSRunAlertPanel(sFileError, [NSString stringWithFormat: sFileNotExistWantBackup____, sAttributes, attributesPath, sAttributes, sAttributes], sYES, sNO, nil, nil);
          if (result == NSAlertDefaultReturn)
            {
              /* Check whether it is a new version */
              if (([self count] > 0) && 
                  ([self uniqueNumberAtIndex: 0] == NSNotFound))
                {
                  [self _reIndexUniqueNumber];
                }
	      return YES;
	    }
	}
    }
  [container removeAllObjects];
  return YES;
}

- (BOOL) unloadSourceAtPath: (NSString *) path
{
  /* Always saved to fixed file */
  if ([super unloadSourceAtPath: nil] == NO) 
    {
      int result = NSRunAlertPanel(sFileErrorWrite, [NSString stringWithFormat: sCannotSaveSource_, [self path]], sDontQuit, sQuit, nil, nil);
      if (result == NSAlertDefaultReturn)
        return NO;
    }
  return YES;
}

@end
