/*
 Copyright (C) 2000-2003 SKYRIX Software AG

 This file is part of OGo

 OGo 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, or (at your option) any
 later version.

 OGo 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 OGo; see the file COPYING.  If not, write to the
 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.
 */
// $Id: SOPEXStatisticsController.m 1 2004-08-20 11:17:52Z znek $
//  Created by znek on Thu Feb 12 2004.

#import "SOPEXStatisticsController.h"


@interface SOPEXStatisticsController (PrivateAPI)
- (void)parseXMLData:(NSData *)xmlData;
- (void)setCurrentPageKey:(NSString *)key;
@end


@implementation SOPEXStatisticsController

#pragma mark -
#pragma mark ### INIT & DEALLOC ###

- (id)initWithApplicationURL:(NSString *)url
{
    NSString *path;
    NSData *data;

    [super init];
    
    [NSBundle loadNibNamed:@"SOPEXStats" owner:self];
    NSAssert(self->window != nil, @"Problem loading SOPEXStats.nib!");

    self->applicationURL = [[NSURL URLWithString:url] retain];
    self->statsURL = [[NSURL URLWithString:[NSString stringWithFormat:@"%@/x/WOStats", url]] retain];

    [self->baseURLTextField setStringValue:[self->applicationURL description]];

    path = [[NSBundle bundleForClass:isa] pathForResource:@"SOPEXStatisticsNatLang" ofType:@"plist"];
    NSAssert(path != nil, @"Couldn't find SOPEXStatisticsNatLang.plist!");
    data = [NSData dataWithContentsOfFile:path];
    NSAssert(data != nil, @"Couldn't load SOPEXStatisticsNatLang.plist!");
    self->natLangDict = [[NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:NULL] retain];

    self->applicationStats = [[NSMutableArray alloc] initWithCapacity:20];
    self->pageNames = [[NSMutableArray alloc] initWithCapacity:20];
    self->statsForPageNameLUT = [[NSMutableDictionary alloc] initWithCapacity:20];
    return self;
}

- (void)dealloc
{
    [self->window orderOut:self];
    [self setCurrentPageKey:nil];
    [self->applicationStats release];
    [self->pageNames release];
    [self->statsForPageNameLUT release];
    [self->natLangDict release];
    [self->applicationURL release];
    [self->statsURL release];
    [super dealloc];
}


#pragma mark -
#pragma mark ### PRIVATE ###


- (void)parseXMLData:(NSData *)xmlData
{
    NSXMLParser *parser;
    
    parser = [[NSXMLParser alloc] initWithData:xmlData];
    [parser setDelegate:self];
    
    [self->applicationStats removeAllObjects];
    [self->pageNames removeAllObjects];
    [self->statsForPageNameLUT removeAllObjects];

    [self setCurrentPageKey:nil];
    self->characterBuffer = [[NSMutableString alloc] init];

    [parser parse];
    if([parser parserError] != nil)
    {
        NSLog(@"%s PARSER ERROR! error:%@", __PRETTY_FUNCTION__, [[parser parserError] localizedDescription]);
    }
    [parser release];

    [self->characterBuffer release];
    self->characterBuffer = nil;

    [self->applicationStatsTableView reloadData];
    [self->pageStatsOutlineView reloadData];
}


#pragma mark -
#pragma mark ### ACTIONS ###


- (IBAction)orderFront:(id)sender
{
    [self->window makeKeyAndOrderFront:sender];
    [self performRefresh:self];
}

- (IBAction)performRefresh:(id)sender
{
    NSURLRequest *request;
    NSData *xmlStats;

    [self->refreshButton setEnabled:NO];
    [self->refreshProgressIndicator startAnimation:self];
    
    // stats = [self->statsURL resourceDataUsingCache:NO];
    // this leads to mayhem, as NSURL's resourceDataUsingCache: method boasts about being
    // able to decompress gzip'ed data, but doesn't do it automatically

    request = [NSURLRequest requestWithURL:self->statsURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];
    NSLog(@"%s retrieving from URL:%@", __PRETTY_FUNCTION__, self->statsURL);
    xmlStats = [NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL];

    NSLog(@"%s retrieved %d bytes.", __PRETTY_FUNCTION__, [xmlStats length]);
    [self parseXMLData:xmlStats];

    [self->refreshProgressIndicator stopAnimation:self];
    [self->refreshButton setEnabled:YES];
}


- (IBAction)openApplicationInBrowser:(id)sender
{
    [[NSWorkspace sharedWorkspace] openURL:self->applicationURL];
}


#pragma mark -
#pragma mark ### WINDOW DELEGATE ###


- (void)windowWillClose:(NSNotification *)aNotification
{
}


#pragma mark -
#pragma mark ### NSXMLPARSER DELEGATE ###


- (void)setCurrentPageKey:(NSString *)key
{
    [key retain];
    [self->currentPageKey release];
    self->currentPageKey = key;
    
    if(key != nil)
    {
        [self->pageNames addObject:key];

        self->currentStats = [[NSMutableArray alloc] initWithCapacity:20];
        [self->statsForPageNameLUT setObject:self->currentStats forKey:key];
        [self->currentStats release];
    }
}


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
    if([elementName isEqualToString:@"page"])
    {
        [self setCurrentPageKey:[attributeDict objectForKey:@"name"]];
    }
    else if([elementName isEqualToString:@"application"])
    {
        [self->pidTextField setStringValue:[attributeDict objectForKey:@"pid"]];
        self->currentStats = self->applicationStats;
    }
    else if([elementName isEqualToString:@"pages"])
    {
    }
    [self->characterBuffer deleteCharactersInRange:NSMakeRange(0, [self->characterBuffer length])];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
    NSMutableDictionary *currentStatDict;
    NSString *tmp;
    NSString *key;

    if([elementName isEqualToString:@"application"] || [elementName isEqualToString:@"page"] || [elementName isEqualToString:@"pages"])
        return;

    key = [self->natLangDict objectForKey:elementName];
    if(key == nil)
        key = elementName;
    if([key isEqualToString:@""])
        key = nil;

    if(key != nil)
    {
        currentStatDict = [[NSMutableDictionary alloc] initWithCapacity:2];
        [currentStatDict setObject:key forKey:@"property"];
        tmp = [self->characterBuffer copy];
        [currentStatDict setObject:tmp forKey:@"value"];
        [tmp release];
        [self->currentStats addObject:currentStatDict];
    }
    else
    {
        if([elementName isEqualToString:@"statisticsDate"])
        {
            tmp = [self->characterBuffer copy];
            [self->lastRefreshDateTextField setStringValue:tmp];
            [tmp release];
        }
        else
        {
            NSLog(@"%s Suppressing addition of elementName:%@", __PRETTY_FUNCTION__, elementName);
        }
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    [self->characterBuffer appendString:string];
}


#pragma mark -
#pragma mark ### NSTABLEVIEW DELEGATE ###


- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
    return [self->applicationStats count];
}

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
    return [[self->applicationStats objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]];
}


#pragma mark -
#pragma mark ### NSTABLEVIEW DELEGATE ###


- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
    if(item == nil)
        return [self->pageNames count];
    
    if([item isKindOfClass:[NSString class]])
        return [[self->statsForPageNameLUT objectForKey:item] count];
    return 0;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
    if(item == nil)
        return YES;
    return [self->pageNames containsObject:item];
}

- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
{
    NSArray *statsList;
    
    if(item == nil)
        statsList = self->pageNames;
    else
        statsList = [self->statsForPageNameLUT objectForKey:item];
    return [statsList objectAtIndex:index];
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
    if([item isKindOfClass:[NSString class]])
        if([[tableColumn identifier] isEqualToString:@"name"])
            return item;
        else
            return nil;
    return [item objectForKey:[tableColumn identifier]];
}

@end
