/*
    Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004 Benhur Stein
    
    This file is part of Pajé.

    Pajé is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the
    Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    Pajé 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 Lesser General Public License
    for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Pajé; if not, write to the Free Software Foundation, Inc.,
    59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
//

#include "HierarchyBrowser.h"
#include "Macros.h"

@interface NSObject (HierarchyBrowserDelegate)
- (void)hierarchyBrowserContainerSelected:(HierarchyBrowser *)sender;
@end

@implementation HierarchyBrowser

- (id)initWithFilter:(PajeFilter *)f
{
    self = [super init];
    if (self) {
        filter = f; // not retained
        if (![NSBundle loadNibNamed:@"HierarchyBrowser" owner:self])
            NSRunAlertPanel(@"HierarchyBrowser", @"Couldn't load interface file",
                            nil, nil, nil);
    }
    return self;
}

- (void)dealloc
{
    // filter is not retained, do not release it.
    Assign(containerTypesBrowser, nil);
    Assign(containersBrowser, nil);
    Assign(splitView, nil);
    containersOnly = NO;
    [super dealloc];
}

- (void)awakeFromNib
{
    NSWindow *window;
    window = [splitView window];
    [splitView retain];
    [splitView removeFromSuperview];
#ifndef GNUSTEP
    [window release];
#endif
}

- (void)refresh
{
    [containersBrowser loadColumnZero];
    [containerTypesBrowser loadColumnZero];
    //if (selection)
    //    [self select:selection];
}

- (void)refreshLastColumn
{
// FIXME: this is wrong. sometimes it should be lastcolumn-1
    [containersBrowser reloadColumn:[containersBrowser /*selected*/lastColumn]];
}

- (void)setFilter:(PajeFilter *)f
{
    filter = f; // not retained
    [self refresh];
}

- (void)setContainersOnly:(BOOL)flag
{
    containersOnly = flag;
}

- (NSView *)view
{
    return splitView;
}


- (PajeEntityType *)selectedEntityType
{
    NSCell *selectedCell;
    PajeEntity *selectedEntity;
    selectedCell = [containersBrowser selectedCell];
    selectedEntity = [selectedCell representedObject];
    return [selectedEntity entityType];
}

- (NSArray *)selectedContainers
{
    NSMutableArray *array = [NSMutableArray array];
    NSEnumerator *cellEnum = [[containersBrowser selectedCells] objectEnumerator];
    NSCell *cell;
    while ((cell = [cellEnum nextObject]) != nil) {
        [array addObject:[cell representedObject]];
    }
    return array;
}

- (void)selectContainers:(NSArray *)containers
{
// FIXME: this is wrong. sometimes it should be lastcolumn-1
    NSMatrix *matrix = [containersBrowser matrixInColumn:[containersBrowser lastColumn]];
    NSCell *cell;
    int row = 0;

//NSLog(@"matrix=%@ [%@]", matrix, [[matrix cellAtRow:row column:0] representedObject]);
    while ((cell = [matrix cellAtRow:row column:0]) != nil) {
//NSLog(@"select? %@", [cell representedObject]);
        if ([containers indexOfObjectIdenticalTo:[cell representedObject]] != NSNotFound) {
            [matrix selectCellAtRow:row column:0];
        }
        row++;
    }
}

- (NSArray *)selectedNames
{
    NSMutableArray *array = [NSMutableArray array];
    NSEnumerator *cellEnum = [[containersBrowser selectedCells] objectEnumerator];
    NSCell *cell;
    while ((cell = [cellEnum nextObject]) != nil) {
        [array addObject:[cell stringValue]];
    }
    return array;
}

- (PajeContainer *)selectedParentContainer
{
    return [[(NSCell *)[containersBrowser selectedCell] representedObject]
	                                                             container];
}



- (void)_syncBottom:(id)sender
    // Make visible columns in bottom browser same as top one
{
    int first = [containerTypesBrowser firstVisibleColumn];
    int last = [containerTypesBrowser lastVisibleColumn];
    while ([containersBrowser lastColumn] < last)
        [containersBrowser addColumn];
    if ([containersBrowser firstVisibleColumn] > first)
        [containersBrowser scrollColumnToVisible:first];
    if ([containersBrowser lastVisibleColumn] < last)
        [containersBrowser scrollColumnToVisible:last];
}

- (void)_syncTop:(id)sender
    // Make visible columns in top browser same as bottom one
{
    int first = [containersBrowser firstVisibleColumn];
    int last = [containersBrowser lastVisibleColumn];
//    return;
    if ([containerTypesBrowser firstVisibleColumn] > first)
        [containerTypesBrowser scrollColumnToVisible:first];
    if ([containerTypesBrowser lastVisibleColumn] < last)
        [containerTypesBrowser scrollColumnToVisible:last];
}

// NSBrowser actions

- (IBAction)containerTypeSelected:(NSBrowser *)sender
{
    if ([sender selectedColumn] != 0) {
        if ([containersBrowser selectedCellInColumn:[sender selectedColumn]-1] == nil) {
            [containersBrowser selectRow:0 inColumn:[sender selectedColumn]-1];
        }
    }
    [containersBrowser reloadColumn:[sender selectedColumn]];
    //[containersBrowser reloadColumn:[sender selectedColumn] + 1];
}

- (IBAction)containerSelected:(NSBrowser *)sender
{
    if ([filter respondsToSelector:@selector(hierarchyBrowserContainerSelected:)]) {
        [filter hierarchyBrowserContainerSelected:self];
    }
}



// NSBrowser  delegate

- (void)browser:(NSBrowser *)sender createRowsForColumn:(int)column
       inMatrix:(NSMatrix *)matrix
{
    if (sender == containerTypesBrowser)
        [self containerTypesBrowser:sender createRowsForColumn:column
                           inMatrix:matrix];
    else if (sender == containersBrowser)
        [self containersBrowser:sender createRowsForColumn:column
                       inMatrix:matrix];
    else
        NSDebugLog(@"Unknown browser in HierarchyBrowser");
}

- (void)containersBrowser:(NSBrowser *)sender createRowsForColumn:(int)column inMatrix:(NSMatrix *)matrix
{
    id upperContainer;
    NSEnumerator *containerEnum;
    PajeContainer *container;
    id containerType;
    int row;
    NSBrowserCell *cell;
    BOOL isContainer;

    if (column == 0) {
        upperContainer = [filter rootInstance];
    } else {
        NSCell *selectedCell;
        selectedCell = [sender selectedCellInColumn:column-1];
        upperContainer = [selectedCell representedObject];
    }

    cell = [containerTypesBrowser selectedCellInColumn:column];
    containerType = [cell representedObject];
    if (containerType == nil) {
        return;
    }
    isContainer = ![cell isLeaf];

    if (isContainer || containersOnly) {
        containerEnum = [filter enumeratorOfContainersTyped:containerType
                                                inContainer:upperContainer];
    } else {
        containerEnum = [[filter allValuesForEntityType:containerType] objectEnumerator];
    }
    for (row = 0; (container = [containerEnum nextObject]) != nil; row++) {
        NSBrowserCell *cell;
        [matrix renewRows:row+1 columns:1];
        cell = [matrix cellAtRow:row column:0];
        [cell setRepresentedObject:container];
        [cell setStringValue:[container name]];
        [cell setLeaf:!isContainer];
    }
    if ([containerTypesBrowser lastColumn] < column) {
//        NSLog(@"antesB: %d, %d", [containerTypesBrowser lastColumn], column);
        [containerTypesBrowser addColumn];
//        NSLog(@"depoisB: %d, %d", [containerTypesBrowser lastColumn], column);
    }
}

- (void)containerTypesBrowser:(NSBrowser *)sender
          createRowsForColumn:(int)column
                     inMatrix:(NSMatrix *)matrix
{
    int rows;
    NSEnumerator *typeEnum;
    PajeEntityType *containerType;
    PajeEntityType *entityType;
    
    if (column == 0) {
        containerType = [filter rootEntityType];
    } else {
        containerType = [(NSCell *)[sender selectedCellInColumn:column-1]
                                 representedObject];
    }
    rows=0;
    typeEnum = [[filter containedTypesForContainerType:containerType] objectEnumerator];
    while ((entityType = [typeEnum nextObject]) != nil) {
        NSBrowserCell *cell;
        BOOL isContainer = [filter isContainerEntityType:entityType];
        if (containersOnly && !isContainer) {
            continue;
        }
        rows++;
        [matrix renewRows:rows columns:1];
        cell = [matrix cellAtRow:rows-1 column:0];
        [cell setRepresentedObject:entityType];
        [cell setStringValue:[entityType description]];
        // FIXME: if containersOnly, containers that do not contain containers
        //        should be leaves
        [cell setLeaf:!isContainer];
    }
}

- (void)browserDidScroll:(NSBrowser *)sender
{
    // one browser scrolled. sync the other one.
    // do delayed performing because visibleColumns are not yet updated when this method is called (at least in OS4.2).
    if (sender == containerTypesBrowser)
        [self _syncBottom:self];//[self performSelector:@selector(_syncBottom:) withObject:self afterDelay:1.0];
    else
        [self _syncTop:self];//[self performSelector:@selector(_syncTop:) withObject:self afterDelay:1.0];
}
@end
