/*
    Document.m

    Implementation of the Document class for the KeyArcher application.

    Copyright (C) 2006  Saso Kiselkov

    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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#import "Document.h"

#import <AppKit/NSBrowser.h>
#import <AppKit/NSBrowserCell.h>
#import <AppKit/NSMatrix.h>
#import <AppKit/NSPanel.h>
#import <AppKit/NSTableColumn.h>
#import <AppKit/NSTableView.h>

#import <Foundation/NSBundle.h>
#import <Foundation/NSException.h>
#import <Foundation/NSNull.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>

#import "ArchivedObject.h"
#import "ObjectGraph.h"

@implementation Document

- (void) dealloc
{
  TEST_RELEASE (graph);

  [super dealloc];
}

- (BOOL) loadDataRepresentation: (NSData *) data ofType: (NSString *) aType
{
  NSDictionary * propertyList;
  NSString * error;

  propertyList = [NSPropertyListSerialization
    propertyListFromData: data
        mutabilityOption: NSPropertyListImmutable
                  format: NULL
        errorDescription: &error];
  if (propertyList == nil)
    {
      NSRunAlertPanel (_(@"Error reading archive"),
        _(@"Error parsing archive's property list: %@"),
        nil, nil, nil, error);

      return NO;
    }

  if (![propertyList isKindOfClass: [NSDictionary class]])
    {
      NSRunAlertPanel (_(@"Error reading archive"),
        _(@"Property list of archive not a dictionary"),
        nil, nil, nil);

      return NO;
    }

  graph = [[ObjectGraph alloc] initWithKeyedArchive: propertyList];
  if (graph == nil)
    {
      return NO;
    }

  return YES;
}

- (NSData *) dataRepresentationOfType: (NSString *) aType
{
  return nil;
}

- (NSString *) windowNibName
{
  return @"Document";
}

- (void) refreshObjectDisplay: sender
{
  [classTable reloadData];
  [attributesTable reloadData];
}

- (void) browser: (NSBrowser *)sender createRowsForColumn: (int)column
  inMatrix: (NSMatrix *)matrix
{
  NSString * path = [browser path];
  id object = [graph objectAtPath: path];

  if ([object isKindOfClass: [ArchivedObject class]])
    {
      NSEnumerator * e;
      NSString * relationship;

      e = [[object relationshipNames] objectEnumerator];
      while ((relationship = [e nextObject]) != nil)
        {
          NSBrowserCell * cell;

          [matrix addRow];
          cell = [matrix cellAtRow: [matrix numberOfRows] - 1 column: 0];

          [cell setTitle: relationship];
          [cell setLeaf: NO];
        }
    }
  else
    {
      NSBrowserCell * cell;

      [matrix addRow];
      cell = [matrix cellAtRow: 0 column: 0];

      [cell setObjectValue: object];      
      [cell setLeaf: YES];
    }

  [matrix sizeToCells];
}

- (int) numberOfRowsInTableView: (NSTableView *)aTableView
{
  NSString * path = [browser path];
  id object = [graph objectAtPath: path];

  if (object != nil)
    {
      if (![object isKindOfClass: [ArchivedObject class]])
        {
          if (aTableView == attributesTable)
            {
              return 0;
            }
          else
            {
              return 1;
            }
        }
      else
        {
          if (aTableView == attributesTable)
            {
              return [[object attributeNames] count];
            }
          else
            {
              return [[graph classInheritanceForUID: [object classUID]] count];
            }
        }
    }
  else
    {
      return 0;
    }
}

- (id) tableView: (NSTableView *)aTableView 
objectValueForTableColumn: (NSTableColumn *)aTableColumn 
             row: (int)rowIndex
{
  NSString * path = [browser path];
  ArchivedObject * object = [graph objectAtPath: path];

  if (object != nil)
    {
      if (![object isKindOfClass: [ArchivedObject class]])
        {
          return [object className];
        }
      else
        {
          if (aTableView == attributesTable)
            {
              NSString * attribute = [[object attributeNames]
                objectAtIndex: rowIndex];
              id value = [object valueOfAttribute: attribute];
              NSString * identifier = [aTableColumn identifier];

              if ([identifier isEqualToString: @"Attribute"])
                {
                  return attribute;
                }
              else if ([identifier isEqualToString: @"Value"])
                {
                  return value;
                }
              else if ([identifier isEqualToString: @"Type"])
                {
                  if ([value isKindOfClass: [NSNull class]])
                    {
                      return _(@"NULL object");
                    }
                  else if ([value isKindOfClass: [NSNumber class]])
                    {
                      return _(@"Number/Boolean object");
                    }
                  else if ([value isKindOfClass: [NSString class]])
                    {
                      return _(@"String");
                    }
                  else
                    {
                      return _(@"Unknown");
                    }
                }
              else
                {
                  return nil;
                }
            }
          else
            {
              return [[graph classInheritanceForUID: [object classUID]]
                objectAtIndex: rowIndex];
            }
        }
    }
  else
    {
      return nil;
    }
}

@end
