// Copyright 1997-2000 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "OHHTMLDocument.h"

#import <Foundation/Foundation.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>
#import <OWF/OWF.h>
#import <OWF/OWPipeline.h>

#import "OHDocumentView.h"
#import "OHHTMLPageView.h"
#import "OHForm.h"
#import "OHViewCell.h"
#import "OHColorPalette.h"
#import "OWScriptDocumentProxy.h"
#import "OWScriptContext.h"
#import "OWPipeline-ScriptExtensions.h"
#import "OWContentInfo-Scripting.h"

RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniHTML/View.subproj/OHHTMLDocument.m,v 1.21 2000/01/20 00:28:03 kc Exp $")

@implementation OHHTMLDocument

- initWithHTMLViewClass:(Class)htmlViewClass;
{
    OFZone *myZone;
    
    if (![super initWithHTMLViewClass:htmlViewClass htmlDocument:self])
        return nil;

    myZone = [OFZone zoneForObject:self];
    contentInfo = [[OWContentInfo allocWithZone:[myZone nsZone]] initWithContent:self typeString:@"HTML"];
    htmlOwners = [[NSMutableArray allocWithZone:[myZone nsZone]] initWithCapacity:1];
    forms = [[NSMutableArray allocWithZone:[myZone nsZone]] init];
    documentImages = [[NSMutableArray allocWithZone:[myZone nsZone]] init];
    documentApplets = [[NSMutableArray allocWithZone:[myZone nsZone]] init];
    documentInfoLock = [[NSLock allocWithZone:[myZone nsZone]] init];
    havePostedLoadEvent = NO;

    return self;
}

- init;
{
    return [self initWithHTMLViewClass:[OHHTMLPageView class]];
}

- (void)dealloc;
{
    unsigned int nullifyIndex, nullifyCount;

    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    [contentInfo nullifyContent];
    [contentInfo release];
    
    [documentInfoLock lock];
    nullifyCount = [htmlOwners count];
    for (nullifyIndex = 0; nullifyIndex < nullifyCount; nullifyIndex++)
        [(OHHTMLOwner *)[htmlOwners objectAtIndex:nullifyIndex] nullifyHTMLDocument];
    [htmlOwners release];
    htmlOwners = nil;
    nullifyCount = [forms count];
    for (nullifyIndex = 0; nullifyIndex < nullifyCount; nullifyIndex++)
        [(OHForm *)[forms objectAtIndex:nullifyIndex] setHTMLDocument:nil];
    [forms release];
    forms = nil;
    firstFormKeyElement = nil;
    lastFormKeyElement = nil;
    [documentImages release];
    documentImages = nil;
    [documentApplets release];
    documentApplets = nil;
    [documentInfoLock unlock];
    [documentInfoLock release];

    [documentColorPalette release];
    documentColorPalette = nil;
    
    [super dealloc];
}


// API

- (OHHTMLPageView *)htmlPageView;
{
    return (OHHTMLPageView *)htmlView;
}

// Building document

- (void)addHTMLOwner:(OHHTMLOwner *)anHTMLOwner;
{
    [documentInfoLock lock];
    [htmlOwners addObject:anHTMLOwner];
    [documentInfoLock unlock];
}

- (void)addForm:(OHForm *)aForm;
{
    OHViewCell *nextFormFirstKeyElement;

    [documentInfoLock lock];
    [forms addObject:aForm];

    //hook form keyViews together
    if ((nextFormFirstKeyElement = [aForm firstKeyElement])) {
        if (!firstFormKeyElement) {
            firstFormKeyElement = nextFormFirstKeyElement;
            lastFormKeyElement = [aForm lastKeyElement];
        } else {
            [lastFormKeyElement setNextKeyViewCell:nextFormFirstKeyElement];
            lastFormKeyElement = [aForm lastKeyElement];
            [lastFormKeyElement setNextKeyViewCell:firstFormKeyElement];
        }
    }
    [documentInfoLock unlock];
}

- (void)setPipeline:(OWPipeline *)aPipe
{
//    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pipelineNotification:) name:OWPipelineTreeDeactivationNotificationName object:aPipe];
}

// Scripting interaction

- (OWScriptDocumentProxy *)scriptProxy
{
    /* For reasons explained elsewhere, the document proxy is associated with a document's pipeline; and the logic for finding the right pipeline is in OWContentInfo. */
    return [contentInfo documentProxy];
}

- (void)documentDidDeactivate:(OHHTMLView *)document;
{
    OBASSERT(document == htmlView);

    /* invalidate will also post an Unload event */
    [[contentInfo existingScriptContext] invalidate];

    [super documentDidDeactivate:document];
}

- (BOOL)contentIsValid
{
    OWScriptContext *scriptContext = [contentInfo existingScriptContext];
    if (scriptContext && ![scriptContext isValid])
        return NO;

    return [super contentIsValid];
}

- (NSArray *)forms;
{
    NSArray *returnValue;

    [documentInfoLock lock];
    returnValue = [NSArray arrayWithArray:forms];  /* shallow copy */
    [documentInfoLock unlock];

    return returnValue;
}

- (OHViewCell *)firstFormKeyElement;
{
    OHViewCell *returnValue;

    [documentInfoLock lock];
    returnValue = [[firstFormKeyElement retain] autorelease];
    [documentInfoLock unlock];

    return returnValue;
}

- (OHViewCell *)lastFormKeyElement;
{
    OHViewCell *returnValue;

    [documentInfoLock lock];
    returnValue = [[lastFormKeyElement retain] autorelease];
    [documentInfoLock unlock];

    return returnValue;
}

- (OHColorPalette *)colorPalette
{
    OHColorPalette *returnedPalette;
    
    [documentInfoLock lock];
    returnedPalette =  documentColorPalette ? [[documentColorPalette retain] autorelease] : [OHColorPalette defaultPalette];
    [documentInfoLock unlock];

    return returnedPalette;
}

- (void)setColorPalette:(OHColorPalette *)aPalette
{
    [documentInfoLock lock];
    [documentColorPalette autorelease];
    documentColorPalette = [aPalette retain];
    [documentInfoLock unlock];
}

- (NSArray *)images
{
    NSArray *returnValue;

    [documentInfoLock lock];
    returnValue = [NSArray arrayWithArray:documentImages];
    [documentInfoLock unlock];

    return returnValue;
}

- (void)addImage:(OHInlineImageCell *)anImage
{
    [documentInfoLock lock];
    [documentImages addObject:anImage];
    [documentInfoLock unlock];
}

- (NSArray *)applets
{
    NSArray *returnValue;

    [documentInfoLock lock];
    returnValue = [NSArray arrayWithArray:documentApplets];
    [documentInfoLock unlock];

    return returnValue;
}

- (void)addApplet:(OHAppletCell *)anApplet
{
    [documentInfoLock lock];
    [documentApplets addObject:anApplet];
    [documentInfoLock unlock];
}

// OHDocument protocol

- (NSView <OHDocumentView> *)omniDocumentView;
{
    return htmlView;
}

// OWContent protocol

- (OWContentType *)contentType;
{
    return [OHDocumentView contentType];
}

- (OWContentInfo *)contentInfo;
{
    return contentInfo;
}

// Debugging

- (NSMutableDictionary *)debugDictionary;
{
    NSMutableDictionary *debugDictionary;

    debugDictionary = [super debugDictionary];

    if (forms)
        [debugDictionary setObject:forms forKey:@"forms"];

    return debugDictionary;
}

@end
