/*
 * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
#ifndef WebCoreBridge_h
#define WebCoreBridge_h
    
#include <glib.h>
#include <gdk/gdk.h> // Gdk Events

#include "WebCoreKeyboardAccess.h"

class KWQKHTMLPart;
class KHTMLView;
class RenderArena;
class QPainter;
class CGContext;

typedef CGContext* CGContextRef;

namespace khtml {
    class RenderPart;
    class RenderObject;
}

typedef khtml::RenderPart KHTMLRenderPart;

#if KWIQ
// moved to external file
#include "WebCoreDeviceType.h"
#else
typedef enum {
    WebCoreDeviceScreen,
    WebCoreDevicePrinter
} WebCoreDeviceType;
#endif

typedef enum {
    WebSelectByMoving,
    WebSelectByExtending
} WebSelectionAlteration;

typedef enum {
    WebSelectForward,
    WebSelectBackward,
    WebSelectRight,
    WebSelectLeft
} WebSelectionDirection;

typedef enum {
    WebSelectByCharacter,
    WebSelectByWord,
    WebSelectByLine,
    WebSelectByParagraph
} WebSelectionGranularity;

class WebCoreSettings;
class WebCoreResourceHandle;
class WebCoreResourceLoader;
class WebCoreResponse;
class KWIQPageCache;
class KWIQPageState;
class WebCoreElementInfo;

namespace WebCoreDOM {
class DOMCSSStyleDeclaration;
class DOMDocument;
class DOMDocumentFragment;
class DOMElement;
class DOMHTMLElement;
class DOMNode;
class DOMRange;
} 
class WebCoreSettings;
class WebScriptObject;


class NSEvent;
class NSView;

// REMOVEUS
class QMouseEvent;
class QKeyEvent;


typedef struct _GtkWidget GtkWidget;

extern gchar* WebCoreElementFrameKey;
extern gchar* WebCoreElementImageAltStringKey;
extern gchar* WebCoreElementImageKey;
extern gchar* WebCoreElementImageRectKey;
extern gchar* WebCoreElementImageURLKey;
extern gchar* WebCoreElementIsSelectedKey;
extern gchar* WebCoreElementLinkURLKey;
extern gchar* WebCoreElementLinkTargetFrameKey;
extern gchar* WebCoreElementLinkLabelKey;
extern gchar* WebCoreElementLinkTitleKey;
extern gchar* WebCoreElementTitleKey;


class WebCoreDOMTreeCopier
{
    // Top-down tree walker.
public:
    class Node {
    public:
	virtual ~Node();
    };

    virtual ~WebCoreDOMTreeCopier() {};
    virtual Node* nodeWithName(const gchar* name, const gchar* value,  const gchar* source, Node* parent) = 0;
};

class WebCoreRenderTreeCopier
{
    // Top-down tree walker.
public:
    class Node {
    public:
	virtual ~Node();
    };

    virtual ~WebCoreRenderTreeCopier(){};

    virtual Node* nodeWithName(const gchar* name, int x, int y, GdkRectangle* rect, GtkWidget* view, Node* parent) = 0;
};


// WebCoreBridge objects are used by WebCore to abstract away operations that need
// to be implemented by library clients, for example WebKit. The objects are also
// used in the opposite direction, for simple access to WebCore functions without dealing
// directly with the KHTML C++ classes.

// A WebCoreBridge creates and holds a reference to a KHTMLPart.

// The WebCoreBridge interface contains methods for use by the non-WebCore side of the bridge.

class WebCoreBridge
{    
    // @interface -- the core side of the bridge  
  
private:
    KWQKHTMLPart* _part;
    KHTMLRenderPart* _renderPart;
    RenderArena *_renderPartArena;
    bool _drawSelectionOnly;
    bool _shouldCreateRenderers;

    // const gchar wrappers;
    gchar * _url;
    gchar * _name;
    gchar * _referrer;
    gchar * _renderTree;
    gchar * _jsEvalString;
    gchar * _encoding;

    void _setupRootForPrinting(bool onOrOff);
    void drawRect(GdkRectangle* rect, QPainter *p);
public:
    WebCoreBridge();
    virtual ~WebCoreBridge();
    void init();

    void initializeSettings(WebCoreSettings *settings);    

    void setRenderPart(KHTMLRenderPart *renderPart);
    KHTMLRenderPart* renderPart();

    void setName(const gchar* name);
    const gchar* name();

    KWQKHTMLPart* part();
    
    void setParent(WebCoreBridge* parent);

    void provisionalLoadStarted();

    void openURL(const gchar* URL, 
		 bool reload, 
		 const gchar* contentType, 
		 const gchar* refresh, 
		 GTime lastModified, 
		 KWIQPageCache *pageCache);

    void setEncoding(const gchar* encoding, bool userChosen);
    void addData(const char* data, int length);
    void closeURL();

    void didNotOpenURL(const gchar* URL);

    void saveDocumentState();
    void restoreDocumentState();

    bool canCachePage();
    bool saveDocumentToPageCache();

    void end();

    const gchar* URL();
    const gchar* referrer();
    
    void installInFrame(GtkWidget* widget);
    void removeFromFrame() ;

    void scrollToAnchor(const gchar* a);
    void scrollToAnchorWithURL(const gchar* a);

    void createKHTMLViewWithGtkWidget(GtkWidget* widget, int marginWidth, int marginHeight);

    bool isFrameSet();

    void reapplyStylesForDeviceType(WebCoreDeviceType deviceType);
    void forceLayoutAdjustingViewSize(bool adjustSizeFlag);
    void forceLayoutWithMinimumPageWidth(float minPageWidth, float maximumPageWidth, float maxPageWidth, bool flag);
    void sendResizeEvent();
    bool needsLayout();
    void setNeedsLayout();

    void drawRect(GdkRectangle *rect, CGContextRef gc);
    void adjustPageHeightNew(float *newBottom,float oldTop, float oldBottom, float bottomLimit);
#if 0
    NSArray* computePageRectsWithPrintWidth(float printWidth, float printHeight);
#endif

    void setUsesInactiveTextBackgroundColor(bool uses);
    bool usesInactiveTextBackgroundColor();
    void mouseDown(GdkEvent * event);
    void mouseUp(GdkEvent * event);
    void mouseMoved(GdkEventMotion * event);    
    void mouseDragged(GdkEventMotion * event);

    GtkWidget* nextKeyView();
    GtkWidget* previousKeyView();

    GtkWidget* nextKeyViewInsideWebFrameViews();
    GtkWidget* previousKeyViewInsideWebFrameViews();

    WebCoreDOMTreeCopier::Node* copyDOMTree(WebCoreDOMTreeCopier* copier);
    WebCoreRenderTreeCopier::Node* copyRenderTree(WebCoreRenderTreeCopier* copier);
    const gchar* renderTreeAsExternalRepresentation();
    
    void elementAtPoint(int x, int y, WebCoreElementInfo* info);

    bool searchFor(const gchar* string, bool forward, bool caseSensitive, bool wrap);
    void jumpToSelection();

    void setTextSizeMultiplier(float multiplier);
    const gchar* textEncoding();

    const gchar* stringByEvaluatingJavaScriptFromString(const gchar* string);

    WebCoreDOM::DOMDocument* DOMDocument();
    WebCoreDOM::DOMHTMLElement* frameElement();

    bool interceptKeyEvent(GdkEventKey *event, bool autoRepeat);

    void setShouldCreateRenderers(bool f);
    bool shouldCreateRenderers();
    int numPendingOrLoadingRequests();

    void bodyBackgroundColor(GdkColor* outColor);

    void adjustViewSize();

    void updateAllViews();

    // KWIQ
    bool hasStaticBackground();    

    // @protocol --  the client side of the bridge
     
public:
    // returns WebCoreBridge objects 
    virtual GList* childFrames()=0; 
    
    virtual WebCoreBridge* mainFrame()=0;
    
    virtual WebCoreBridge* findFrameNamed(const gchar* name)=0;

    // Creates a name for an frame unnamed in the HTML. It should produce repeatable results for loads of the same frameset.  
    virtual const gchar* generateFrameName()=0; 

    virtual void frameDetached()=0;

    virtual GtkWidget* documentView()=0;
    
    virtual void loadURL(const gchar* URL, const gchar* referrer, bool reload, bool onLoadEvent, const gchar* target, NSEvent *event, WebCoreDOM::DOMElement* form, GHashTable* formValues)=0;
    virtual void postWithURL(const gchar* URL, const gchar* referrer, const gchar* target, GByteArray* data, const gchar* contentType, NSEvent *event, WebCoreDOM::DOMElement *form, GHashTable *formValues)=0;

    virtual WebCoreBridge* createWindowWithURL(const gchar* URL, const gchar* name)=0;
    virtual void showWindow()=0;

    virtual const gchar* userAgentForURL(const gchar* URL)=0;

    virtual void setTitle(const gchar* title)=0;
    virtual void setStatusText(const gchar* status)=0;

    virtual void setIconURL(const gchar* URL)=0;
    virtual void setIconURL(const gchar* URL, const gchar* string)=0;

    virtual WebCoreBridge* createChildFrameNamed(const gchar* frameName, 
				      const gchar* URL,
				      KHTMLRenderPart *renderPart,
				      bool allowsScrolling, 
				      int marginWidth, 
				      int marginHeight)=0;


    virtual bool areToolbarsVisible()=0;
    virtual void setToolbarsVisible(bool visible)=0;
    virtual bool isStatusBarVisible()=0;
    virtual void setStatusBarVisible(bool visible)=0;
    virtual bool areScrollbarsVisible()=0;
    virtual void setScrollbarsVisible(bool visible)=0;

    virtual void setWindowFrame(GdkRectangle* rect)=0;
    virtual void windowFrame(GdkRectangle* outRect)=0;
    virtual void setWindowContentRect(GdkRectangle* rect)=0;
    virtual void windowContentRect(GdkRectangle* outRect)=0;

    virtual void setWindowIsResizable(bool resizable)=0;
    virtual bool windowIsResizable()=0;
    
    virtual GtkWidget *firstResponder()=0;
    virtual void makeFirstResponder(GtkWidget *view)=0;

    virtual void closeWindowSoon()=0;

    virtual void runJavaScriptAlertPanelWithMessage(const gchar* message)=0;
    virtual bool runJavaScriptConfirmPanelWithMessage(const gchar* message)=0;
    virtual bool runJavaScriptTextInputPanelWithPrompt(const gchar* prompt, 
						       const gchar* defaultText, 
						       gchar** result)=0;
    virtual void addMessageToConsole(const gchar* message, unsigned lineNumber, const gchar* sourceURL)=0;

    virtual WebCoreResourceHandle* startLoadingResource(WebCoreResourceLoader *loader, 
						    const gchar* URL, 
                                                    GHashTable* headers, 
						    GByteArray* requestBody)=0;
    virtual WebCoreResourceHandle* startLoadingResource(WebCoreResourceLoader *loader,
						    const gchar* URL, 
						    GHashTable* headers)=0;
    virtual void objectLoadedFromCacheWithURL(const gchar* URL, WebCoreResponse* response, unsigned bytes)=0;

    virtual void syncLoadResourceWithURL(const gchar* URL,
					 GHashTable* requestHeaders, 
					 GByteArray* postData,
					 GByteArray* outResponseData,
					 gchar** outFinalURL, 
					 GHashTable* outResponseHeaders,
					 int* outStatusCode) = 0;

    virtual bool isReloading()=0;


    virtual void reportClientRedirectToURL(const gchar* URL, 
					   double seconds, 
					   GTime date, 
					   bool lockHistory, 
					   bool isJavaScriptFormAction)=0;
    virtual void reportClientRedirectCancelled(bool cancelWithLoadInProgress)=0;

    virtual void focusWindow()=0;
    virtual void unfocusWindow()=0;

    virtual GtkWidget* nextKeyViewOutsideWebFrameViews()=0;
    virtual GtkWidget* previousKeyViewOutsideWebFrameViews()=0;

    virtual bool defersLoading()=0;
    virtual void setDefersLoading(bool loading)=0;
    virtual void saveDocumentState(GList* documentState)=0; 
    virtual GList* documentState()=0;  


    virtual void setNeedsReapplyStyles()=0;

    virtual const gchar* requestedURLString()=0;
    virtual const gchar* incomingReferrer()=0;

    virtual GtkWidget* widgetForPluginWithURL(const gchar* URL,
					    GList* attributesArray,
					    const gchar* baseURLString,
					    const gchar* MIMEType) = 0;

    virtual bool saveDocumentToPageCache(KWIQPageState *documentInfo)=0;

    virtual int getObjectCacheSize()=0;

    virtual bool frameRequiredForMIMEType(const gchar* mimeType, const gchar* URL)=0;

    virtual void loadEmptyDocumentSynchronously()=0;

    virtual const gchar* MIMETypeForPath(const gchar* path)=0;

    virtual void handleMouseDragged(NSEvent *event)=0;
    virtual void handleAutoscrollForMouseDragged(NSEvent *event)=0;
    virtual bool mayStartDragWithMouseDragged(NSEvent *event)=0;

    virtual int historyLength()=0;
    virtual void goBackOrForward(int distance)=0;

    virtual void setHasBorder(bool hasBorder)=0;

    virtual WebCoreKeyboardUIMode keyboardUIMode()=0;
 
    virtual void didSetName(const gchar* name) =0;

    virtual void print()=0;
#if 0
    virtual jobject pollForAppletInView(NSView *view)=0;
    NSUndoManager *undoManager;
#endif
    
    virtual void issueCutCommand()=0;
    virtual void issueCopyCommand()=0;
    virtual void issuePasteCommand()=0;
    virtual void respondToChangedSelection()=0;
    virtual void respondToChangedContents()=0;
#if 0
    virtual bool interceptEditingKeyEvent(NSEvent *event)=0;
    virtual void setIsSelected(bool isSelected, NSView *view)=0;
    virtual bool isEditable()=0;
    virtual bool shouldBeginEditing(DOMRange *range)=0;
    virtual bool shouldEndEditing(DOMRange *range)=0;
#endif
    virtual const gchar* overrideMediaTypes()=0;
    virtual void windowObjectCleared()=0;    
};




/* POD struct (for now)
 * strings must be freed */ 
struct WebCoreElementInfo
{
    gboolean isSelected;
    gchar* linkTitle;
    gchar* linkLabel;
    gchar* linkURL;
    gchar* linkTarget;
    // x = y = w = h= -1 if there's no image */
    GdkRectangle imageRect;
    gchar* imageURL;
    gchar* imageAltText;
    WebCoreElementInfo();
};

#endif
