#import "MWExportWatcher.h"
#import "MGWPopUpButton.h"
#import "MWFakeFile.h"
#import "TAMSCharEngine.h"
#import "myResults.h"
#import "tams.h"
#import "utils.h"
#import "tamsutils.h"
#import "prefBoss.h"
#import "stringCategories.h"

#define TABFMT 1
#define COMMAFMT 2
#define NLFMT 3
#define CRFMT 4
#define XMLFMT 5
#define OTHERFMT 99
int moveInArray(id who, NSMutableArray *theArray, int row);

@implementation MWExportWatcher
-(id) init
{
    [super init];
    colPool = [[NSMutableArray alloc] init];
    colList = [[NSMutableArray alloc] init];
    dndList = [[NSMutableArray alloc] init];
    return self;
}
-(void) dealloc
{
    [colPool release];
    [colList release];
    [dndList release];
    [super dealloc];
}
-(NSString *) XprocessString: (NSString *) who line: (int) ln
{
    NSString *ss;
    NSMutableString *s2, *s3, *s4;
    //get the selected row
    //get the appropriate data
    
    if([who length])
    {
        ss = who;
        
        //set it to the textview
        s2 = [[NSMutableString alloc] init];
        s3 = [[NSMutableString alloc] init];
        s4 = [[NSMutableString alloc] init];
        [s2 setString: ss];
        [s2 replaceOccurrencesOfString: @"\\n" withString: @"\n"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
        [s2 replaceOccurrencesOfString: @"\\t" withString: @"\t"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
        [s2 replaceOccurrencesOfString: @"\\r" withString: @"\r"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
        if([tagSwitch state] == NSOffState)
        {
            MWFakeFile *mf;
            TAMSCharEngine *tx;
            ctQChar *qq;
            qq = [[ctQChar alloc] init];
            
            
            mf = [[MWFakeFile alloc] initWithString: s2];
            tx = [[TAMSCharEngine alloc] initWithFile: mf];
            [tx setAllowTab: 1];
            [tx setNoPar: 0];
            [tx startSearch];
            while([tx scanNext: qq withWarnings: NO] != ENDOFFILE)
            {
                if([qq tokentype] == CHAR)
                {
                    [s3 appendString: [qq buff]];
                }
            }
            [tx release];
            [qq release];
            [mf release];
            
        }
        else
            [s3 setString: s2];
        [s3 replaceOccurrencesOfString: @"\\n" withString: @"\n"
                               options: NSLiteralSearch range: NSMakeRange(0, [s3 length])];
        [s3 replaceOccurrencesOfString: @"\\t" withString: @"\t"
                               options: NSLiteralSearch range: NSMakeRange(0, [s3 length])];
        [s3 replaceOccurrencesOfString: @"\\r" withString: @"\r"
                               options: NSLiteralSearch range: NSMakeRange(0, [s3 length])];
        
        if([gPrefBoss TAScanForLN] && ln > 0)
        {
            [s4 setString: [NSString stringWithFormat: @"%d\t%@", 
               ln,
                s3]];
        }
        else
        {
            [s4 setString: s3];
        }
        [s2 release];
        [s3 release];
        return s4;
        /*put colorize stuff here */
        //if([self global: @"nonregexcharflag"] || [self global: @"regexcharflag"]) return;
        
    }
}

-(NSString *) processString: (NSString *) who line: (int) ln
{
    NSMutableString *s2, *s3, *s4;
    //get the selected row
    //get the appropriate data

    if([tagSwitch state] == NSOnState && [escapeSwitch state] == NSOnState)
        return who;
    if([who length] == 0) return who;
    
    s3 = [[NSMutableString alloc] init];
    s4 = [[NSMutableString alloc] init];
    s2 = [[NSMutableString alloc] init];
    [s2 setString: who];
    if([escapeSwitch state] == NSOffState)
    {
        [s2 replaceOccurrencesOfString: @"\\n" withString: @"\n"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
        [s2 replaceOccurrencesOfString: @"\\t" withString: @"\t"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
        [s2 replaceOccurrencesOfString: @"\\r" withString: @"\r"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
    }
    
/* useless
    if([escapeSwitch state] == NSOffState)
    {
         
        //set it to the textview
        [s2 replaceOccurrencesOfString: @"\\n" withString: @"\n"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
        [s2 replaceOccurrencesOfString: @"\\t" withString: @"\t"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
        [s2 replaceOccurrencesOfString: @"\\r" withString: @"\r"
                               options: NSLiteralSearch range: NSMakeRange(0, [s2 length])];
    }
*/
    if([tagSwitch state] == NSOffState)
    {
        TAMSCharEngine *tx;
        ctQChar *qq;
        qq = [[ctQChar alloc] init];
        
        
        tx = [[TAMSCharEngine alloc] initWithString: s2];
        if([escapeSwitch state] == NSOffState)
        {
            [tx setAllowTab: 1];
            [tx setNoPar: 0];
        }
        else
        {
            [tx setAllowTab: 0];
            [tx setNoPar: 1];
        }
        [tx startSearch];
        while([tx scanNext: qq withWarnings: NO] != ENDOFFILE)
        {
            if([qq tokentype] == CHAR)
            {
                [s3 appendString: [qq buff]];
            }
        }
        [tx release];
        [qq release];
        
    }
    else
        [s3 setString: s2];
/*
    if([escapeSwitch state] == NSOffState)
    {
        [s3 replaceOccurrencesOfString: @"\\n" withString: @"\n"
                               options: NSLiteralSearch range: NSMakeRange(0, [s3 length])];
        [s3 replaceOccurrencesOfString: @"\\t" withString: @"\t"
                               options: NSLiteralSearch range: NSMakeRange(0, [s3 length])];
        [s3 replaceOccurrencesOfString: @"\\r" withString: @"\r"
                               options: NSLiteralSearch range: NSMakeRange(0, [s3 length])];
    }
    else
        [s3 replaceOccurrencesOfString: @"\\" withString: @"\\\\"
                               options: 0 range: NSMakeRange(0, [s3 length])];
    */
    
    if([gPrefBoss TAScanForLN] && ln > 0)
    {
        if([escapeSwitch state] == NSOffState)
            [s4 setString: [NSString stringWithFormat: @"%d\t%@", ln, s3]];
        else
            [s4 setString: [NSString stringWithFormat: @"%d\\t%@", ln, s3]];
            
    }
    else
    {
        [s4 setString: s3];
    }
    [s2 release];
    [s3 release];
    [s4 autorelease];
    return s4;
}
-(NSMutableString *) getDataString
{
    NSMutableString *fs = [NSMutableString string];
    NSMutableString *rs = [NSMutableString string];
    //NSMutableString *opentag = [NSMutableString string];
    //NSMutableString *closetag = [NSMutableString string];
    NSMutableString *ans = [[NSMutableString alloc] init];
    NSArray *myData;
    int i,j,n,m;
    int format;
    NSEnumerator *nnn;
    NSNumber *ndx;
    nnn = [fieldList selectedRowEnumerator];
    format = [[formatMenu selectedItem] tag];
    [colList removeAllObjects];
    while((ndx = [nnn nextObject]) != nil)
    {
        [colList addObject: [colPool objectAtIndex: [ndx intValue]]];
    }
    if([colList count] < 1)
    {
        NSWARNING(@"Select fields for export");
        return [NSMutableString string];
    }
    if([selectedSwitch state] == NSOnState)
        myData = [theBoss hotData];
    else
        myData = [theBoss allData];
    
    switch(format)
    {
        case TABFMT:
            [fs setString: @"\t"];
            [rs setString: @"\n"];
            break;
        case COMMAFMT:
            [fs setString: @","];
            [rs setString: @"\n"];
            break;
        case NLFMT:
            [fs setString: @"\n"];
            [rs setString: @"\n"];
            break;
        case CRFMT:
            [fs setString: @"\r"];
            [rs setString: @"\r"];
            break;
        case XMLFMT:
            [fs setString: @"\n"];
            [rs setString: @"\n"];
            break;
        case OTHERFMT:
            [fs setString: [[colDelim stringValue] stringUnescaped]];
            [rs setString: [[rowDelim stringValue] stringUnescaped]];
            break;
            
    };
    n = [myData count];
    m = [colList count];
    if(format == XMLFMT)
    { 
        [ans appendString: @"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"];
        [ans appendString: @"\n<tamsdata>\n"]; 

    }
    else if ([headerSwitch state] == NSOnState)
    {
        for(j = 0; j < m; j++)
        {
            if(j > 0) 
            {
                [ans appendString: fs];
                [ans appendString: [[[colList objectAtIndex: j] copy] autorelease]];
            }
            else
                [ans appendString: [[[colList objectAtIndex: j] copy] autorelease]];
            
        }
        [ans appendString: rs];
        
    }
    for(i = 0; i < n; i++)
    {
        if(format == XMLFMT) [ans appendString: @"<tamsrecord>\n"];
        for(j = 0; j < m; j++)
        {
            NSString *md, *fldname;
            NSDictionary *rcrd;
            int ln = [[[myData objectAtIndex: i] objectForKey: @"_line_number"] intValue];
            rcrd = [myData objectAtIndex: i];
            fldname = [colList objectAtIndex: j];
            if([fldname isEqualToString: @"_beg_loc"])
                md = [(NSNumber *)[rcrd objectForKey: fldname] stringValue];
            else if([fldname isEqualToString: @"_doc"])
                md = [(MWFile *)[rcrd objectForKey: fldname] name];
            else
                md = [[myData objectAtIndex: i] objectForKey: [colList objectAtIndex: j]];
            if([[colList objectAtIndex: j] isEqualToString: @"_data"] == NO)
                ln = -1;
            
            if(format != XMLFMT)
            {
                if(j > 0)
                {
                    [ans appendString: fs];
                    [ans appendString: [self processString: md line: ln]];
                    
                }
                else
                    [ans appendString: [self processString: md line: ln]];
            }
            else
            {
                [ans appendString: [NSString stringWithFormat: @"\t<%@>%@</%@>\n",
                    [colList objectAtIndex: j],
                    [self processString: md line: ln],
                    [colList objectAtIndex: j]]];
            }
            
        }
        if(format == XMLFMT) [ans appendString: @"</tamsrecord>"];
        [ans appendString: rs];
    }
    if(format == XMLFMT) [ans appendString: @"\n</tamsdata>"];

    [ans autorelease];
    return ans;
            
}
-(void) savePanelDidEnd: (NSSavePanel *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo
{
    
    if(returnCode == NSOKButton)
    {
        NSString *myName = [sheet filename];
        NSString *md = [self getDataString];
        [md writeToFile: myName atomically: YES];
        
    }
    else
    {
        
    }
}

- (IBAction)exitExport:(id)sender
{
    [thePane orderOut: sender];
    [NSApp endSheet: thePane returnCode: 0];

    
}

- (IBAction)runExport:(id)sender
{
    NSSavePanel *msp;
    
    if([clipboardSwitch state] == NSOffState)
    {
        msp = [NSSavePanel savePanel];
        [msp setDelegate: self];
        if([[formatMenu selectedItem] tag] == XMLFMT)
            [msp setRequiredFileType: @"xml"];
        else
            [msp setRequiredFileType: @"txt"];
        [msp beginSheetForDirectory: nil file: nil modalForWindow: thePane modalDelegate: self didEndSelector: @selector(savePanelDidEnd:returnCode:contextInfo:) contextInfo: nil];
    }
    else
    {
        BOOL a;
        NSString *ans = [self getDataString];
        [ans retain];
        [[NSPasteboard generalPasteboard]
	declareTypes:[NSArray arrayWithObject:NSStringPboardType]
               owner:self];
        
        a = [[NSPasteboard generalPasteboard] setString: ans forType: NSStringPboardType];
        [ans autorelease];
        
        //get string
        //copy to clipboard
    }
    //[thePane orderOut: sender];
    //[NSApp endSheet: thePane returnCode: 1];
    
    
}


- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)operation
{
    if(tableView == fieldList)
        return  NSDragOperationMove;//NSDragOperationEvery
    else
        return    NSDragOperationNone ;
}

- (int)numberOfRowsInTableView:(NSTableView *) tt
{
    if(tt == fieldList)
        return [colPool count];
    else return 0;
}
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
    if(aTableView == fieldList)
        return [colPool objectAtIndex: rowIndex];
    else return @"";
}    
- (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray *)rows toPasteboard:(NSPasteboard *)pboard
{
    id testid;
    testid = fieldList;
    
    if(tableView == fieldList)
    {
        /*
         
         [dndList removeAllObjects];
         FORALL(rows)
         {
             [dndList addObject: [colPool objectAtIndex: [temp intValue]]];
         }
         ENDFORALL;
         [pboard setString: [dndList objectAtIndex: 0] forType: NSStringPboardType];
         return YES;
         */
#ifdef SINGLEDRAG
        if([rows count] != 1) return NO;
        dndNdx = [[rows objectAtIndex: 0] intValue];
        [pboard setString: [colPool objectAtIndex: [[rows objectAtIndex: 0] intValue]] forType: NSStringPboardType];
        return YES;
#else
        [dndList removeAllObjects];
        FORALL(rows)
        {
            [dndList addObject: [colPool objectAtIndex: [temp intValue]]];
        }
        ENDFORALL;
        [pboard	declareTypes:[NSArray arrayWithObject:NSStringPboardType]
               owner:self];
        [pboard setString: [colPool objectAtIndex: [[rows objectAtIndex: 0] intValue]] forType: NSStringPboardType];
        return YES;
#endif
        
    }
    else return NO;
}

- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)operation
{
    int n;
    if(tableView == fieldList)
    {
        int currSpot;
        n = [dndList count];
        currSpot = row;
        FORALL(dndList)
        {
            currSpot = moveInArray(temp, colPool, currSpot);
        }
        ENDFORALL;
        [tableView reloadData];
        [tableView deselectAll: nil];
        FORALL(dndList)
        {
            [tableView selectRow: [colPool indexOfObject: temp] byExtendingSelection: YES];
        }
        ENDFORALL;
        [dndList removeAllObjects];
        return YES;
        
    }
    else return NO;
}

-(void) exportDidEnd: (NSWindow *) mySheet returnCode: (int) returnCode contextInfo: (void *) contextInfo
{
    
    if(returnCode)
    {
        
    }
    
}


-(void) doExport
{
    NSWindow *who;
    if([gPrefBoss detachedSheetValue])
        who = nil;
    else
        who = theWindow;
    
    [fieldList setVerticalMotionCanBeginDrag: YES];
    [fieldList registerForDraggedTypes: [NSArray arrayWithObjects: NSStringPboardType, nil]];
    [clipboardSwitch setState: NSOnState];
    [escapeSwitch setState: NSOffState];
    [tagSwitch setState: NSOffState];
    [headerSwitch setState: NSOffState];
    [selectedSwitch setState: NSOnState];
    [formatMenu selectItemWithTag: 1];
    [colDelim setStringValue: @""];
    [rowDelim setStringValue: @""];
    [colPool removeAllObjects];
    columns = [theBoss tableColumns];
    FORALL(columns)
    {
        NSString *idfr = [temp identifier];
        if([idfr isEqualToString: @"#"])
            continue;
#ifdef COLFILTER
        else if([idfr isEqualToString: @"_code"] || [idfr isEqualToString: @"_data"])
            [colPool addObject: [[idfr copy] autorelease]];
        else if([idfr characterAtIndex: 0] == '_')
            continue;
        else
#endif
            [colPool addObject: [[idfr copy] autorelease]];
    }
    ENDFORALL;
    [fieldList deselectAll: nil];
    [fieldList reloadData];
    [NSApp beginSheet: thePane
       modalForWindow: who
	modalDelegate: self
       didEndSelector: @selector(exportDidEnd:returnCode:contextInfo:)
          contextInfo: nil];
    
    
}
@end
