/*
 * Copyright (C) 2004, 2005, 2006, 2008 Apple 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 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 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. 
 */

#import "config.h"
#import "Widget.h"

#if PLATFORM(IOS)

#import "Cursor.h"
#import "Document.h"
#import "FontCascade.h"
#import "Frame.h"
#import "GraphicsContext.h"
#import "PlatformMouseEvent.h"
#import "ScrollView.h"
#import "WAKScrollView.h"
#import "WAKView.h"
#import "WAKWindow.h"
#import "WebCoreFrameView.h"
#import "WebCoreView.h"
#import <wtf/BlockObjCExceptions.h>

@interface NSView (WebSetSelectedMethods)
- (void)setIsSelected:(BOOL)isSelected;
- (void)webPlugInSetIsSelected:(BOOL)isSelected;
@end

namespace WebCore {

static void safeRemoveFromSuperview(NSView *view)
{
    // FIXME: we should probably change the first responder of the window if
    // it is a descendant of the view we remove.
    // See: <rdar://problem/10360186>
    [view removeFromSuperview];
}

Widget::Widget(NSView* view)
{
    init(view);
}

Widget::~Widget() 
{
    releasePlatformWidget();
}

// FIXME: Should move this to Chrome; bad layering that this knows about Frame.
void Widget::setFocus(bool focused)
{
    UNUSED_PARAM(focused);
}

void Widget::setCursor(const Cursor&)
{
}

void Widget::show()
{
    if (isSelfVisible())
        return;

    setSelfVisible(true);

    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    [getOuterView() setHidden:NO];
    END_BLOCK_OBJC_EXCEPTIONS;
}

void Widget::hide()
{
    if (!isSelfVisible())
        return;

    setSelfVisible(false);

    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    [getOuterView() setHidden:YES];
    END_BLOCK_OBJC_EXCEPTIONS;
}

IntRect Widget::frameRect() const
{
    if (!platformWidget())
        return m_frame;
    
    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    return enclosingIntRect([getOuterView() frame]);
    END_BLOCK_OBJC_EXCEPTIONS;
    
    return m_frame;
}

void Widget::setFrameRect(const IntRect &rect)
{
    m_frame = rect;
    
    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    NSView *v = getOuterView();
    NSRect f = rect;
    if (!NSEqualRects(f, [v frame])) {
        [v setFrame:f];
        [v setNeedsDisplay: NO];
    }
    END_BLOCK_OBJC_EXCEPTIONS;
}

NSView* Widget::getOuterView() const
{
    NSView* view = platformWidget();

    // If this widget's view is a WebCoreFrameScrollView then we
    // resize its containing view, a WebFrameView.
    if ([view conformsToProtocol:@protocol(WebCoreFrameScrollView)]) {
        view = [view superview];
        ASSERT(view);
    }

    return view;
}

void Widget::paint(GraphicsContext& p, const IntRect& r, SecurityOriginPaintPolicy)
{
    if (p.paintingDisabled())
        return;
    
    NSView *view = getOuterView();

    CGContextRef cgContext = p.platformContext();
    CGContextSaveGState(cgContext);

    NSRect viewFrame = [view frame];
    NSRect viewBounds = [view bounds];
    CGContextTranslateCTM(cgContext, viewFrame.origin.x - viewBounds.origin.x, viewFrame.origin.y - viewBounds.origin.y);

    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    [view displayRectIgnoringOpacity:[view convertRect:r fromView:[view superview]] inContext:cgContext];
    END_BLOCK_OBJC_EXCEPTIONS;

    CGContextRestoreGState(cgContext);
}

void Widget::setIsSelected(bool /*isSelected*/)
{
}

void Widget::addToSuperview(NSView *view)
{
    BEGIN_BLOCK_OBJC_EXCEPTIONS;

    ASSERT(view);
    NSView *subview = getOuterView();

    if (!subview)
        return;

    ASSERT(![view isDescendantOf:subview]);
    
    if ([subview superview] != view)
        [view addSubview:subview];

    END_BLOCK_OBJC_EXCEPTIONS;
}

void Widget::removeFromSuperview()
{
    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    safeRemoveFromSuperview(getOuterView());
    END_BLOCK_OBJC_EXCEPTIONS;
}

IntRect Widget::convertFromRootToContainingWindow(const Widget* rootWidget, const IntRect& rect)
{
    if (!rootWidget->platformWidget())
        return rect;

    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    ASSERT([rootWidget->platformWidget() isKindOfClass:[NSScrollView class]]);
    WAKScrollView *view = static_cast<WAKScrollView *>(rootWidget->platformWidget());
    if (WAKView *documentView = [view documentView])
        return enclosingIntRect([documentView convertRect:rect toView:nil]);
    return enclosingIntRect([view convertRect:rect toView:nil]);
    END_BLOCK_OBJC_EXCEPTIONS;

    return rect;
}

IntRect Widget::convertFromContainingWindowToRoot(const Widget* rootWidget, const IntRect& rect)
{
    if (!rootWidget->platformWidget())
        return rect;

    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    ASSERT([rootWidget->platformWidget() isKindOfClass:[NSScrollView class]]);
    WAKScrollView *view = static_cast<WAKScrollView *>(rootWidget->platformWidget());
    if (WAKView *documentView = [view documentView])
        return enclosingIntRect([documentView convertRect:rect fromView:nil]);
    return enclosingIntRect([view convertRect:rect fromView:nil]);
    END_BLOCK_OBJC_EXCEPTIONS;

    return rect;
}

IntPoint Widget::convertFromRootToContainingWindow(const Widget* rootWidget, const IntPoint& point)
{
    if (!rootWidget->platformWidget())
        return point;

    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    ASSERT([rootWidget->platformWidget() isKindOfClass:[NSScrollView class]]);
    WAKScrollView *view = static_cast<WAKScrollView *>(rootWidget->platformWidget());
    NSPoint convertedPoint;
    if (WAKView *documentView = [view documentView])
        convertedPoint = [documentView convertPoint:point toView:nil];
    else
        convertedPoint = [view convertPoint:point toView:nil];
    return IntPoint(roundf(convertedPoint.x), roundf(convertedPoint.y));
    END_BLOCK_OBJC_EXCEPTIONS;

    return point;
}

IntPoint Widget::convertFromContainingWindowToRoot(const Widget* rootWidget, const IntPoint& point)
{
    if (!rootWidget->platformWidget())
        return point;

    BEGIN_BLOCK_OBJC_EXCEPTIONS;
    ASSERT([rootWidget->platformWidget() isKindOfClass:[NSScrollView class]]);
    WAKScrollView *view = static_cast<WAKScrollView *>(rootWidget->platformWidget());
    NSPoint convertedPoint;
    if (WAKView *documentView = [view documentView])
        convertedPoint = IntPoint([documentView convertPoint:point fromView:nil]);
    else
        convertedPoint = IntPoint([view convertPoint:point fromView:nil]);
    return IntPoint(roundf(convertedPoint.x), roundf(convertedPoint.y));
    END_BLOCK_OBJC_EXCEPTIONS;

    return point;
}

NSView *Widget::platformWidget() const
{
    return m_widget.get();
}

void Widget::setPlatformWidget(NSView *widget)
{
    if (widget == m_widget)
        return;

    m_widget = widget;
}

}

#endif // PLATFORM(IOS)
