/*
 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
 */

#if PLATFORM(IOS_FAMILY)

#import "WebPDFViewIOS.h"
#import "WebDataSourceInternal.h"

#import "WebFrameInternal.h"
#import "WebJSPDFDoc.h"
#import "WebKitVersionChecks.h"
#import "WebPDFDocumentExtras.h"
#import "WebPDFViewPlaceholder.h"
#import <JavaScriptCore/JSContextRef.h>
#import <JavaScriptCore/OpaqueJSString.h>
#import <WebCore/Color.h>
#import <WebCore/Frame.h>
#import <WebCore/FrameLoader.h>
#import <WebCore/FrameLoaderClient.h>
#import <WebCore/GraphicsContext.h>
#import <WebCore/StringWithDirection.h>
#import <WebCore/WKGraphics.h>
#import <WebKitLegacy/WebFrame.h>
#import <WebKitLegacy/WebFrameLoadDelegate.h>
#import <WebKitLegacy/WebFramePrivate.h>
#import <WebKitLegacy/WebFrameView.h>
#import <WebKitLegacy/WebNSViewExtras.h>
#import <WebKitLegacy/WebViewPrivate.h>
#import <wtf/Assertions.h>
#import <wtf/StdLibExtras.h>

using namespace WebCore;
using namespace std;

static int comparePageRects(const void *key, const void *array);

static const float PAGE_WIDTH_INSET     = 4.0 * 2.0;
static const float PAGE_HEIGHT_INSET    = 4.0 * 2.0;

static CGColorRef createCGColorWithDeviceWhite(CGFloat white, CGFloat alpha)
{
    static CGColorSpaceRef graySpace = CGColorSpaceCreateDeviceGray();
    const CGFloat components[] = { white, alpha };
    return CGColorCreate(graySpace, components);
}

@implementation WebPDFView {
    BOOL dataSourceHasBeenSet;
    CGPDFDocumentRef _PDFDocument;
    NSString *_title;
    CGRect *_pageRects;
}

+ (NSArray *)supportedMIMETypes
{
    return @[
        @"text/pdf",
        @"application/pdf",
    ];
}

+ (CGColorRef)shadowColor
{
    static CGColorRef shadowColor = createCGColorWithDeviceWhite(0, 2.0 / 3);
    return shadowColor;
}

+ (CGColorRef)backgroundColor
{
    static CGColorRef backgroundColor = createCGColorWithDeviceWhite(204.0 / 255, 1);
    return backgroundColor;
}

// This is a secret protocol for WebDataSource and WebFrameView to offer us the opportunity to do something different 
// depending upon which frame is trying to instantiate a representation for PDF.
+ (Class)_representationClassForWebFrame:(WebFrame *)webFrame
{
    // If this is not the main frame, use the old WAK PDF view.
    if ([[webFrame webView] mainFrame] != webFrame)
        return [WebPDFView class];
    
    return [WebPDFViewPlaceholder class];
}

- (void)dealloc
{
    if (_PDFDocument != NULL)
        CGPDFDocumentRelease(_PDFDocument);
    free(_pageRects);
    [_title release];
    [super dealloc];
}

- (void)drawPage:(CGPDFPageRef)aPage
{
    CGContextRef context = WKGetCurrentGraphicsContext();
    size_t pageNumber = CGPDFPageGetPageNumber(aPage);
    CGRect pageRect = _pageRects[pageNumber-1];
    
    // Draw page.
    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 2.0f), 3.0f, [[self class] shadowColor]);
    CGContextSetFillColorWithColor(context, cachedCGColor(Color::white));
    CGContextFillRect(context, pageRect);
    CGContextRestoreGState(context);    
    
    CGContextSaveGState(context);

    CGContextTranslateCTM(context, CGRectGetMinX(pageRect), CGRectGetMinY(pageRect));
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextTranslateCTM(context, 0, -CGRectGetHeight(pageRect));

    CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(aPage, kCGPDFCropBox, CGRectMake(0.0, 0.0, CGRectGetWidth(pageRect), CGRectGetHeight(pageRect)), 0, true));
    
    CGRect cropBox = CGPDFPageGetBoxRect(aPage, kCGPDFCropBox);
    CGContextClipToRect(context, cropBox);
    
    CGContextDrawPDFPage(context, aPage);
    CGContextRestoreGState(context);    
}

- (NSArray *)_pagesInRect:(CGRect)rect
{
    NSMutableArray *pages = [NSMutableArray array];
    size_t pageCount = CGPDFDocumentGetNumberOfPages(_PDFDocument);
    CGRect *firstFoundRect = (CGRect *)bsearch(&rect, _pageRects, pageCount, sizeof(CGRect), comparePageRects);
    if (firstFoundRect != NULL) {
        size_t firstFoundIndex = firstFoundRect - _pageRects;
        id page = (id)CGPDFDocumentGetPage(_PDFDocument, firstFoundIndex+1);
        ASSERT(page);
        if (!page)
            return pages;
        [pages addObject:page];
        size_t i;
        for (i = firstFoundIndex - 1; i < pageCount; i--) {
            if (CGRectIntersectsRect(CGRectInset(_pageRects[i], 0.0, - PAGE_HEIGHT_INSET * 2), rect)) {
                id page = (id)CGPDFDocumentGetPage(_PDFDocument, i + 1);
                ASSERT(page);
                if (page)
                    [pages addObject:page];
            } else
                break;
        }
        for (i = firstFoundIndex + 1; i < pageCount; i++) {
            if (CGRectIntersectsRect(CGRectInset(_pageRects[i], 0.0, - PAGE_HEIGHT_INSET * 2), rect)) {
                id page = (id)CGPDFDocumentGetPage(_PDFDocument, i + 1);
                ASSERT(page);
                if (page)
                    [pages addObject:page];
            } else
                break;
        }        
    }
    return pages;
}

- (void)drawRect:(CGRect)aRect
{
    CGContextRef context = WKGetCurrentGraphicsContext();

    // Draw Background.
    CGContextSaveGState(context);
    CGContextSetFillColorWithColor(context, [[self class] backgroundColor]);
    CGContextFillRect(context, aRect);
    CGContextRestoreGState(context);

    if (!_PDFDocument)
        return;
    
    CGPDFPageRef page = NULL;
    NSEnumerator * enumerator = [[self _pagesInRect:aRect] objectEnumerator];

    while ((page = (CGPDFPageRef)[enumerator nextObject]))
        [self drawPage:page];
}

- (void)setDataSource:(WebDataSource *)dataSource
{
    // Since this class is a WebDocumentView and WebDocumentRepresentation, setDataSource: will be called twice. Do work only once.
    if (dataSourceHasBeenSet)
        return;

    if (!_title)
        _title = [[[[dataSource request] URL] lastPathComponent] copy];

    WAKView * superview = [self superview];
    
    // As noted above, -setDataSource: will be called twice -- once for the WebDocumentRepresentation, once for the WebDocumentView.
    if (!superview)
        return;

    [self setBoundsSize:[self convertRect:[superview bounds] fromView:superview].size];
    
    dataSourceHasBeenSet = YES;
}

- (void)dataSourceUpdated:(WebDataSource *)dataSource
{

}

- (void)setNeedsLayout:(BOOL)flag
{

}

- (void)layout
{
    // <rdar://problem/7790957> Problem with UISplitViewController on iPad when displaying PDF
    // Since we don't have anything to layout, just repaint the visible tiles.
    [self setNeedsDisplay:YES];
}

- (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow
{

}

- (void)viewDidMoveToHostWindow
{

}

- (void)receivedData:(NSData *)data withDataSource:(WebDataSource *)dataSource
{
}

- (void)receivedError:(NSError *)error withDataSource:(WebDataSource *)dataSource
{
}

- (void)_computePageRects
{
    size_t pageCount = CGPDFDocumentGetNumberOfPages(_PDFDocument);
    _pageRects = (CGRect *)malloc(sizeof(CGRect) * pageCount);    
    
    CGSize size = CGSizeMake(0.0, PAGE_HEIGHT_INSET);
    size_t i;
    for (i = 1; i <= pageCount; i++) {
        
        CGPDFPageRef page = CGPDFDocumentGetPage(_PDFDocument, i);
        CGRect boxRect = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
        CGFloat rotation = CGPDFPageGetRotationAngle(page) * (M_PI / 180);
        if (rotation != 0) {
            boxRect = CGRectApplyAffineTransform(boxRect, CGAffineTransformMakeRotation(rotation));
            boxRect.size.width = roundf(boxRect.size.width);
            boxRect.size.height = roundf(boxRect.size.height);
        }

        _pageRects[i-1] = boxRect;
        _pageRects[i-1].origin.y = size.height;

        size.height += boxRect.size.height + PAGE_HEIGHT_INSET;
        size.width = max(size.width, boxRect.size.width);
    }
    
    size.width += PAGE_WIDTH_INSET * 2.0;
    [self setBoundsSize:size];
    
    for (i = 0; i < pageCount; i++)
        _pageRects[i].origin.x = roundf((size.width - _pageRects[i].size.width) / 2);
}

- (void)_checkPDFTitle
{
    if (!_PDFDocument)
        return;

    NSString *title = nil;

    CGPDFDictionaryRef info = CGPDFDocumentGetInfo(_PDFDocument);
    CGPDFStringRef value;
    if (CGPDFDictionaryGetString(info, "Title", &value))
        title = [(NSString *)CGPDFStringCopyTextString(value) autorelease];

    if ([title length]) {
        [_title release];
        _title = [title copy];
        core([self _frame])->loader().client().dispatchDidReceiveTitle({ title, TextDirection::LTR });
    }
}

- (void)finishedLoadingWithDataSource:(WebDataSource *)dataSource
{
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)[dataSource data]);

    if (!provider) 
        return;
    
    _PDFDocument = CGPDFDocumentCreateWithProvider(provider);
    CGDataProviderRelease(provider);
        
    if (!_PDFDocument)
        return;
    
    [self _checkPDFTitle];
    [self _computePageRects];

    NSArray *scripts = allScriptsInPDFDocument(_PDFDocument);

    if (![scripts count])
        return;

    JSGlobalContextRef ctx = JSGlobalContextCreate(0);
    JSObjectRef jsPDFDoc = makeJSPDFDoc(ctx, dataSource);
    for (NSString *script in scripts)
        JSEvaluateScript(ctx, OpaqueJSString::tryCreate(script).get(), jsPDFDoc, nullptr, 0, nullptr);
    JSGlobalContextRelease(ctx);

    [self setNeedsDisplay:YES];
}

- (BOOL)canProvideDocumentSource
{
    return NO;
}

- (NSString *)documentSource
{
    return nil;
}

- (NSString *)title
{
    return _title;
}

- (unsigned)pageNumberForRect:(CGRect)rect
{
    size_t bestPageNumber = 0;
    if (_PDFDocument != NULL && _pageRects != NULL) {
        NSArray *pages = [self _pagesInRect:rect];
        float bestPageArea = 0;
        size_t count = [pages count];
        size_t i;
        for (i = 0; i < count; i++) {
            size_t pageNumber = CGPDFPageGetPageNumber((CGPDFPageRef)[pages objectAtIndex:i]);
            CGRect intersectionRect = CGRectIntersection(_pageRects[pageNumber - 1], rect);
            float intersectionArea = intersectionRect.size.width * intersectionRect.size.height;
            if (intersectionArea > bestPageArea) {
                bestPageArea = intersectionArea;
                bestPageNumber = pageNumber;
            }
        }
    }
    return bestPageNumber;
}

- (unsigned)totalPages
{
    if (_PDFDocument != NULL)
        return CGPDFDocumentGetNumberOfPages(_PDFDocument);
    return 0;
}

- (CGPDFDocumentRef)doc
{
    return _PDFDocument;
}

- (CGRect)rectForPageNumber:(unsigned)pageNum
{
    return (_pageRects != NULL && pageNum > 0 ? _pageRects[pageNum - 1] : CGRectNull);
}

@end

static int comparePageRects(const void *key, const void *array)
{
    const CGRect *keyRect = (const CGRect *)key;
    const CGRect *arrayRect = (const CGRect *)array;
    if (CGRectIntersectsRect(*arrayRect, *keyRect))
        return 0;
    return CGRectGetMinY(*keyRect) > CGRectGetMaxY(*arrayRect) ? 1 : -1;
}

#endif // PLATFORM(IOS_FAMILY)
