/*$Copyright:
 * Copyright (C) 1992.5.22. Recruit Co.,Ltd. 
 * Institute for Supercomputing Research
 * All rights reserved.
 * NewsBase  by ISR, Kazuto MIYAI, Gary ARAKAKI, Katsunori SUZUKI, Kok-meng Lue
 *
 * You may freely copy, distribute and reuse the code in this program under 
 * following conditions.
 * - to include this notice in the source code, if it is to be distributed 
 *   with source code.
 * - to add the file named "COPYING" within the code, which shall include 
 *   GNU GENERAL PUBLIC LICENSE(*).
 * - to display an acknowledgement in binary code as follows: "This product
 *   includes software developed by Recruit Co.,Ltd., ISR."
 * - to display a notice which shall state that the users may freely copy,
 *   distribute and reuse the code in this program under GNU GENERAL PUBLIC
 *   LICENSE(*)
 * - to indicate the way to access the copy of GNU GENERAL PUBLIC LICENSE(*)
 *
 *   (*)GNU GENERAL PUBLIC LICENSE is stored in the file named COPYING
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
$*/

#import <appkit/Application.h>
#import <appkit/NXBrowser.h>
#import <appkit/Matrix.h>
#import <appkit/graphics.h>
#import <objc/List.h>
#import <mach/mach.h>
#import <string.h>

#import "ITreeBrowser.h"
#import "INXBrowserCellWithLinkedObject.h"
#import "IOrderedListD.h"
#import "InfoD.h"
#import "ITreeNodeD.h"
#import "IUifNode.h"
#import "ITreeBrowserMatrix.h"
#import "INewsGroupTreeControl.h"
#import "errdebug.h"

@implementation ITreeBrowser

- initFrame:(NXRect *)frameRect
{
    [super initFrame:frameRect];
    iAuxAgent = NULL;
    iAuxAction = NULL;
    [self setDelegate:self];
    [self setCellClass:[INXBrowserCellWithLinkedObject class]];
    [self setMatrixClass:[ITreeBrowserMatrix class]];
    
    [self setMultipleSelectionEnabled:YES];
    [self setBranchSelectionEnabled:NO];
    [self setTarget:self];
    [self setAction:@selector(leafPreHandler:)];
    [self useScrollBars:YES];
    [self useScrollButtons:YES];
    [self setPathSeparator:'.'];
    iRootListnode = nil;

    return self;
}

- (void)setIOmodule:io_module
{
    iIOmodule = io_module;
}

- iOmodule
{
    return iIOmodule;
}

- (void)setDataGroupUIF:uif_module
{
    iDataGroupUIF = uif_module;
}

- (void)setItemRepUIF:uif_module
{
    iItemRepUIF = uif_module;
}

- (void)setItemUIF:uif_module
{
    iItemUIF = uif_module;
}

- setRootListnode:node
{
    if (iRootListnode != nil ) {
	[iRootListnode free];
    }

    iRootListnode = node;
    return self;
}

// browser is made of cells(INXBrowserCellWithLinkedObject), and each
// cell has relation to a node(IUifNode) and listnode(IOrderedListD)
//     +---------------------------+
//     | selectedCell --> node     |  +---------------+
//     |               +> listnode +--| cell --> node |
//     +---------------------------+  +---------------+
//                                    | cell --> node |
//     				      +---------------+
//             				:
//					:

- (int)browser:sender fillMatrix:matrix inColumn:(int)column
{
    id		selectedCell;
    id		node;
    id		bcell;
    int		row;
    int		i;
    id 		child_node;
    id		listnode;
    
    /* for loading column-0, listnode is root node */
    if (column == 0) {
	if((listnode = iRootListnode) == nil) {
	/* initialize without column */
	    return 0;
	}
	if ([listnode count] == 0) {
	    /* some code for setting title for empty cell should be here */
	}
    } else {
	/* find selection in previous column */
        selectedCell = [[sender matrixInColumn:(column - 1)] selectedCell];
	if ((listnode=[selectedCell listnode]) != nil) {
	    [listnode free];
	    [selectedCell setListnode:nil];
	}

	// if control key is down, do 'toggleActive' under this tree
	if ((int)[[self matrixInColumn:[self lastColumn]] flagsOfLastEvent] 
    							& NX_CONTROLMASK) {
	    [[self matrixInColumn:[self lastColumn]] resetFlagsOfLastEvent];
	    [self toggleHandler:selectedCell];
	    [[self matrixInColumn:[self lastColumn]] display];
	}

	node = [selectedCell node];    
	listnode = [self directoryHandler:node];
	[selectedCell setListnode:listnode];
    }
    
    for (i = 0, row = 0; child_node = [listnode objectAt:i]; ++i) {
	[matrix addRow];
	bcell = [matrix cellAt:row :0];
	[self loadCell:bcell fromNode:child_node];
	[bcell setLoaded:YES];
	++row;
	/* link this NXBrowserCell with the childNode */
	[bcell setNode:child_node];

	/* bcell is leaf or directory */
	if ([child_node isLeaf]) {
	    [bcell setLeaf:YES];
	} else {
	    [bcell setLeaf:NO];
	}
	/* set cell active or not */
	[bcell setActive:[child_node active]];
    }
    return row;
}

- (void)loadCell:bcell fromNode:childNode
{
    id		image;
    
    [bcell setStringValue:(char *)[childNode titleForCell]];
    
    if ((image = [childNode imageForCell]) != nil) {
	[bcell setImage:image];
    }
    return;
}

// leafPreHandler will be called when
//   1. clicked directory and also
//   2. clicked leaf
//   3. clicked newsfolder in folder dock matrix 
// this routine will handle
//   - control key & click  -> unsubscribe newsgroup
//   - display folder icon
//   - call leafHandler, which will fill article subject in article's Browser
//
- (void)leafPreHandler:sender
{
    id		lastColumnMatrix, bcellList, bcell;
    int		i, hiliCellCount;

    lastColumnMatrix = [self matrixInColumn:[self lastColumn]];
    if ((int)[lastColumnMatrix flagsOfLastEvent] & NX_CONTROLMASK) {
	DBG(1,fprintf(stderr,"-- control key is down"));
	[lastColumnMatrix resetFlagsOfLastEvent];
	[self togglePreHandler:sender];
	return;
    }
    
    // if iTreeBrowser has aux agent, do iAxuAction.
    // now this is used for displaying newsgroup folder icon
    if (iAuxAgent != nil) {
	[iAuxAgent perform:(SEL)iAuxAction with:self];
    }
    
    bcellList = [lastColumnMatrix cellList];
    hiliCellCount=0;
    for (i=0; bcell=[bcellList objectAt:i]; ++i) {
	if ([bcell isHighlighted]) {
	    ++hiliCellCount;
	}
    }
    if (hiliCellCount > 1) {
	return;
    } else {
	[self leafHandler:sender];
    }
    return;
}

- (void)leafHandler:sender
{
    return;
}

- (void)togglePreHandler:sender
{
    id		lastColumnMatrix;
    
    lastColumnMatrix = [self matrixInColumn:[self lastColumn]];
    [lastColumnMatrix sendAction:@selector(toggleHandler:) to:self 
    							forAllCells:NO];
    /* display matrix after sending toggleActive to cell */
    [lastColumnMatrix display];
    return;
}

- (void)toggleHandler:senderCell
{
    id		node;
    
    node = [senderCell node];
    if([iIOmodule toggleActive:node]) {
	/* return YES, if iIOmodule has toggleActive method */
	[senderCell toggleActive];
	if([node active]==YES) {
	    [node setActive:NO];
	} else {
	    [node setActive:YES];
	}
    }
    return;
}

- directoryHandler:node
{
    return [iIOmodule subDirectoryOf:node];
}

- setAuxAgent:auxAgent
{
    iAuxAgent = auxAgent;
    return self;
}

- auxAgent
{
    return iAuxAgent;
}

- setAuxAction:(SEL)auxAction
{
    iAuxAction = auxAction;
    return self;
}

- (SEL)auxAction
{
    return iAuxAction;
}

@end
