/*
    StringsDocument.m - NSDocument subclass for Localize.app
    Copyright (C) 2003 Rob Burns

    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., 675 Mass Ave, Cambridge, MA 02111, USA.
*/

#include <ctype.h>
#include "StringsDocument.h"
#include "StringsDocument+ReadWrite.h"
#include "StringsEntry.h"


@implementation StringsDocument

- (void) dealloc
{
  RELEASE(strings);
  RELEASE(keys_matched);
  RELEASE(keys_translated);
  RELEASE(repeatStrings);
  RELEASE(m_sHeader);
  
  [super dealloc];
}

- (id) init
{
  if( !(self = [super init]) )
    {
      return nil;
    }
  strings = [[NSMutableArray alloc] init];
  keys_translated = [[NSMutableArray alloc] init];
  keys_matched = [[NSMutableArray alloc] init];
  m_sGenerated = NO;
  m_sHeader = [[NSString alloc] init];
  repeatStrings = [[NSMutableArray alloc] init];
  return self;
}

- (NSData *) dataRepresentationOfType: (NSString *)aType
{
  NSData *data;
  NSString *tmpString;
  
  data = [NSData data];  
  tmpString = [self createOutput: [[self fileName] lastPathComponent]];
  data = [self convertOutput: tmpString]; 

  return data;
}

- (BOOL) loadDataRepresentation: (NSData *)docData ofType: (NSString*)docType
{
  NSString *rawString;
  
  if( [docType isEqualToString: @"strings"] &&
    (rawString = [[NSString alloc] initWithData: docData encoding: NSASCIIStringEncoding]) )
    {      
      if( [rawString rangeOfString: @"updated by make_strings"].length != 0 )
        {
          m_sGenerated = YES;
          if( ![self parseInput: rawString] ) return NO;
          [self tagRepeats];
        }
      else
        {
          NSRunInformationalAlertPanel(_(@"Load Failed"),
            _(@"Currently Localize only supports strings files generated by make_strings.\nFuture versions will support generic strings files."),
            _(@"OK"), nil, nil);
          return NO;
        }
      DESTROY(rawString);
      return YES;
    }
  return NO;
}

- (void) makeWindowControllers
{
  EditorWindowController *controller;
  
  if( m_sGenerated )
    controller = AUTORELEASE([[EditorWindowController alloc] initWithWindowNibName: @"MakeStrings"]);
  else
    controller = AUTORELEASE([[EditorWindowController alloc] initWithWindowNibName: @"GenericStrings"]);
  [self addWindowController: controller];
}


// ***************************
// Access and mutation methods
// ***************************


- (BOOL) m_sGenerated
{
  return m_sGenerated;
}

- (NSArray *) strings
{
  return [NSArray arrayWithArray: strings];
}

- (NSString *) keyForString: (StringsEntry *)string
{
  int x = [strings indexOfObject: string];
  if( x < [strings count] )
    return [[strings objectAtIndex: x] key];
  return nil; 
}

- (NSString *) fileForString: (StringsEntry *)string
{
  int x = [strings indexOfObject: string];
  if( x < [strings count] )
    return [[strings objectAtIndex: x] file];
  return nil;}

- (BOOL) stringIsMatched: (StringsEntry *)string
{
  int x = [strings indexOfObject: string];
  if( x < [strings count] )
    return !([[strings objectAtIndex: x] flags]&FLAG_UNTRANSLATED);
  return NO;
}

- (NSString *) valueForString: (StringsEntry *)string
{
  int x = [strings indexOfObject: string];
  if( x < [strings count] )
    return [[strings objectAtIndex: x] translated];
  return nil;
}

- (void) setValue: (NSString *)value forString: (StringsEntry *)string
{
  int x = [strings indexOfObject: string];
  if( x < [strings count] )
    [[strings objectAtIndex: x] setTranslated: value];
} 

- (NSString *) commentForString: (StringsEntry *)string
{
  int x = [strings indexOfObject: string];
  if( x < [strings count] )
    return [[strings objectAtIndex: x] userComment];
  return nil;
}

- (void) setComment: (NSString *)comment forString: (StringsEntry *)string
{
  int x = [strings indexOfObject: string];
  if( x < [strings count] )
    [[strings objectAtIndex: x] setUserComment: comment];
}

- (BOOL) stringIsTranslated: (StringsEntry *)string
{
  int x = [strings indexOfObject: string];
  if( x < [strings count] )
    return !([[strings objectAtIndex: x] flags]&FLAG_UNTRANSLATED);
  return NO;
}

- (void) setTranslated: (BOOL)flag forString: (StringsEntry *)string
{
  // [[strings objectAtIndex: index] setFlags: 02];
}

- (void) deleteString: (StringsEntry *)string
{
  // [strings removeObjectAtIndex: index];
}


// ******************************************
// NSOutlineView DataSource protocol methods
// ******************************************


- (id) outlineView: (NSOutlineView *) outlineView
             child: (int) index
            ofItem: (id) item
{
  int i=0;
  int temp=0;
  NSMutableArray *tA = [NSMutableArray arrayWithCapacity: 1];
 
  if( item == nil )
    {
      for( i=0; i < [strings count]; i++ )
        {
          temp = [[strings objectAtIndex: i] repeatFlag];
          if( temp == 0 || temp == 2 )
            [tA addObject: [NSNumber numberWithInt: i]];
        }
      return [strings objectAtIndex: [[tA objectAtIndex: index] intValue]];    
    }
  if( [item repeatFlag] == 0 )
    {
      return [repeatStrings objectAtIndex: index];
    }
  return nil;
}

- (BOOL) outlineView: (NSOutlineView *) outlineView
    isItemExpandable: (id) item
{
  if( [item repeatFlag] == 0 )
    {
      return YES;
    }  
  return NO;
}

-    (int) outlineView: (NSOutlineView *) outlineView
numberOfChildrenOfItem: (id) item
{
  int i, k, temp; 
  i = k = temp = 0;
 
  if( item == nil )
    {
      for( i=0; i < [strings count]; i++ )
        {
          temp = [[strings objectAtIndex: i] repeatFlag];
          if( temp == 0 || temp == 2 )           
            k++;
        }
      return k; 
    }
  else
    {
      if( [item repeatFlag] == 0 )
        {
          [repeatStrings removeAllObjects];
          for(i = [strings indexOfObject: item] + 1; 
            i < [strings count] && [[strings objectAtIndex: i] repeatFlag] == 1; ++i )
            {
              [repeatStrings addObject: [strings objectAtIndex: i]];
              k++;
            }
          return k;
        }
      return 0;
    }
}

- (id)        outlineView: (NSOutlineView *) outlineView
objectValueForTableColumn: (NSTableColumn *) tableColumn
                   byItem: (id)item
{
  if( [[tableColumn identifier] isEqualToString: @"Keys"] )
    return [item key];
  return nil;
}

 
// ***************
// Private methods
// ***************


- (void) tagRepeats
{
  NSString *previous, *current, *next;
  int i=0;
  
  // special case for the initial entry
  current = [[strings objectAtIndex: 0] key];
  next = [[strings objectAtIndex: 1] key];
  if( current == next )
    [[strings objectAtIndex: 0] setRepeatFlag: 0]; // begin a repeat
  else
    [[strings objectAtIndex: 0] setRepeatFlag: 2]; // not a repeat
 
  for( i=1; i < ([strings count]-1); i++ )
    {
      previous = [[strings objectAtIndex: i-1] key];
      current = [[strings objectAtIndex: i] key];
      next = [[strings objectAtIndex: i+1] key];
      if( current != previous && current == next )
        [[strings objectAtIndex: i] setRepeatFlag: 0]; // begin a repeat
      else if( current == previous )
        [[strings objectAtIndex: i] setRepeatFlag: 1]; // continue a repeat
      else
        [[strings objectAtIndex: i] setRepeatFlag: 2]; // not a repeat
    }

  // special case for the last entry
  current = [[strings objectAtIndex: i] key];
  previous = [[strings objectAtIndex: i-1] key];
  if( current == previous )
    [[strings objectAtIndex: i] setRepeatFlag: 1]; // continue a repeat
  else
    [[strings objectAtIndex: i] setRepeatFlag: 2]; // not a repeat
}


@end


