/*
 * Copyright (C) 2015 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.
 */

#import "config.h"
#import "WKTextFinderClient.h"

#if PLATFORM(MAC)

#import "APIFindClient.h"
#import "APIFindMatchesClient.h"
#import "WebImage.h"
#import "WebPageProxy.h"
#import <algorithm>
#import <pal/spi/mac/NSTextFinderSPI.h>
#import <wtf/BlockPtr.h>
#import <wtf/Deque.h>

// FIXME: Implement scrollFindMatchToVisible.
// FIXME: The NSTextFinder overlay doesn't move with scrolling; we should have a mode where we manage the overlay.

static const NSUInteger maximumFindMatches = 1000;

@interface WKTextFinderClient ()

- (void)didFindStringMatchesWithRects:(const Vector<Vector<WebCore::IntRect>>&)rects didWrapAround:(BOOL)didWrapAround;

- (void)getImageForMatchResult:(id <NSTextFinderAsynchronousDocumentFindMatch>)findMatch completionHandler:(void (^)(NSImage *generatedImage))completionHandler;
- (void)didGetImageForMatchResult:(WebKit::WebImage *)string;

@end

namespace WebKit {
using namespace WebCore;

class TextFinderFindClient : public API::FindMatchesClient, public API::FindClient {
public:
    explicit TextFinderFindClient(WKTextFinderClient *textFinderClient)
        : m_textFinderClient(textFinderClient)
    {
    }

private:
    void didFindStringMatches(WebPageProxy* page, const String&, const Vector<Vector<WebCore::IntRect>>& matchRects, int32_t) override
    {
        [m_textFinderClient didFindStringMatchesWithRects:matchRects didWrapAround:NO];
    }

    void didGetImageForMatchResult(WebPageProxy* page, WebImage* image, int32_t index) override
    {
        [m_textFinderClient didGetImageForMatchResult:image];
    }

    void didFindString(WebPageProxy*, const String&, const Vector<WebCore::IntRect>& matchRects, uint32_t, int32_t, bool didWrapAround) override
    {
        [m_textFinderClient didFindStringMatchesWithRects:{ matchRects } didWrapAround:didWrapAround];
    }

    void didFailToFindString(WebPageProxy*, const String& string) override
    {
        [m_textFinderClient didFindStringMatchesWithRects:{ } didWrapAround:NO];
    }

    RetainPtr<WKTextFinderClient> m_textFinderClient;
};
    
}

@interface WKTextFinderMatch : NSObject <NSTextFinderAsynchronousDocumentFindMatch>

@property (nonatomic, readonly) unsigned index;

@end

@implementation WKTextFinderMatch {
    WKTextFinderClient *_client;
    NSView *_view;
    RetainPtr<NSArray> _rects;
    unsigned _index;
}

- (instancetype)initWithClient:(WKTextFinderClient *)client view:(NSView *)view index:(unsigned)index rects:(NSArray *)rects
{
    self = [super init];

    if (!self)
        return nil;

    _client = client;
    _view = view;
    _rects = rects;
    _index = index;

    return self;
}

- (NSView *)containingView
{
    return _view;
}

- (NSArray *)textRects
{
    return _rects.get();
}

- (void)generateTextImage:(void (^)(NSImage *generatedImage))completionHandler
{
    [_client getImageForMatchResult:self completionHandler:completionHandler];
}

- (unsigned)index
{
    return _index;
}

@end

@implementation WKTextFinderClient {
    WebKit::WebPageProxy *_page;
    NSView *_view;
    Deque<WTF::Function<void(NSArray *, bool didWrap)>> _findReplyCallbacks;
    Deque<WTF::Function<void(NSImage *)>> _imageReplyCallbacks;
}

- (instancetype)initWithPage:(WebKit::WebPageProxy&)page view:(NSView *)view
{
    self = [super init];

    if (!self)
        return nil;

    _page = &page;
    _view = view;
    
    _page->setFindMatchesClient(std::make_unique<WebKit::TextFinderFindClient>(self));
    _page->setFindClient(std::make_unique<WebKit::TextFinderFindClient>(self));

    return self;
}

- (void)willDestroyView:(NSView *)view
{
    _page->setFindMatchesClient(nullptr);
    _page->setFindClient(nullptr);

    _page = nullptr;
    _view = nil;
}

#pragma mark - NSTextFinderClient SPI

- (void)replaceMatches:(NSArray *)matches withString:(NSString *)replacementText inSelectionOnly:(BOOL)selectionOnly resultCollector:(void (^)(NSUInteger replacementCount))resultCollector
{
    Vector<uint32_t> matchIndices;
    matchIndices.reserveCapacity(matches.count);
    for (id match in matches) {
        if ([match isKindOfClass:WKTextFinderMatch.class])
            matchIndices.uncheckedAppend([(WKTextFinderMatch *)match index]);
    }
    _page->replaceMatches(WTFMove(matchIndices), replacementText, selectionOnly, [collector = makeBlockPtr(resultCollector)] (uint64_t numberOfReplacements, auto error) {
        collector(error == WebKit::CallbackBase::Error::None ? numberOfReplacements : 0);
    });
}

- (void)findMatchesForString:(NSString *)targetString relativeToMatch:(id <NSTextFinderAsynchronousDocumentFindMatch>)relativeMatch findOptions:(NSTextFinderAsynchronousDocumentFindOptions)findOptions maxResults:(NSUInteger)maxResults resultCollector:(void (^)(NSArray *matches, BOOL didWrap))resultCollector
{
    // Limit the number of results, for performance reasons; NSTextFinder always
    // passes either 1 or NSUIntegerMax, which results in search time being
    // proportional to document length.
    maxResults = std::min(maxResults, maximumFindMatches);

    unsigned kitFindOptions = 0;

    if (findOptions & NSTextFinderAsynchronousDocumentFindOptionsBackwards)
        kitFindOptions |= WebKit::FindOptionsBackwards;
    if (findOptions & NSTextFinderAsynchronousDocumentFindOptionsWrap)
        kitFindOptions |= WebKit::FindOptionsWrapAround;
    if (findOptions & NSTextFinderAsynchronousDocumentFindOptionsCaseInsensitive)
        kitFindOptions |= WebKit::FindOptionsCaseInsensitive;
    if (findOptions & NSTextFinderAsynchronousDocumentFindOptionsStartsWith)
        kitFindOptions |= WebKit::FindOptionsAtWordStarts;

    RetainPtr<NSProgress> progress = [NSProgress progressWithTotalUnitCount:1];
    auto copiedResultCollector = Block_copy(resultCollector);
    _findReplyCallbacks.append([progress, copiedResultCollector] (NSArray *matches, bool didWrap) {
        [progress setCompletedUnitCount:1];
        copiedResultCollector(matches, didWrap);
        Block_release(copiedResultCollector);
    });

    if (maxResults == 1)
        _page->findString(targetString, static_cast<WebKit::FindOptions>(kitFindOptions), maxResults);
    else
        _page->findStringMatches(targetString, static_cast<WebKit::FindOptions>(kitFindOptions), maxResults);
}

- (void)getSelectedText:(void (^)(NSString *selectedTextString))completionHandler
{
    void (^copiedCompletionHandler)(NSString *) = Block_copy(completionHandler);

    _page->getSelectionOrContentsAsString([copiedCompletionHandler] (const String& string, WebKit::CallbackBase::Error) {
        copiedCompletionHandler(string);
        Block_release(copiedCompletionHandler);
    });
}

- (void)selectFindMatch:(id <NSTextFinderAsynchronousDocumentFindMatch>)findMatch completionHandler:(void (^)(void))completionHandler
{
    ASSERT([findMatch isKindOfClass:[WKTextFinderMatch class]]);
    ASSERT(!completionHandler);

    WKTextFinderMatch *textFinderMatch = static_cast<WKTextFinderMatch *>(findMatch);
    _page->selectFindMatch(textFinderMatch.index);
}

#pragma mark - FindMatchesClient

static RetainPtr<NSArray> arrayFromRects(const Vector<WebCore::IntRect>& matchRects)
{
    RetainPtr<NSMutableArray> nsMatchRects = adoptNS([[NSMutableArray alloc] initWithCapacity:matchRects.size()]);
    for (auto& rect : matchRects)
        [nsMatchRects addObject:[NSValue valueWithRect:rect]];
    return nsMatchRects;
}

- (void)didFindStringMatchesWithRects:(const Vector<Vector<WebCore::IntRect>>&)rectsForMatches didWrapAround:(BOOL)didWrapAround
{
    if (_findReplyCallbacks.isEmpty())
        return;

    auto replyCallback = _findReplyCallbacks.takeFirst();
    unsigned matchCount = rectsForMatches.size();
    RetainPtr<NSMutableArray> matchObjects = adoptNS([[NSMutableArray alloc] initWithCapacity:matchCount]);
    for (unsigned i = 0; i < matchCount; i++) {
        RetainPtr<NSArray> nsMatchRects = arrayFromRects(rectsForMatches[i]);
        RetainPtr<WKTextFinderMatch> match = adoptNS([[WKTextFinderMatch alloc] initWithClient:self view:_view index:i rects:nsMatchRects.get()]);
        [matchObjects addObject:match.get()];
    }

    replyCallback(matchObjects.get(), didWrapAround);
}

- (void)didGetImageForMatchResult:(WebKit::WebImage *)image
{
    if (_imageReplyCallbacks.isEmpty())
        return;

    WebCore::IntSize size = image->bitmap().size();
    size.scale(1 / _page->deviceScaleFactor());

    auto imageCallback = _imageReplyCallbacks.takeFirst();
    imageCallback(adoptNS([[NSImage alloc] initWithCGImage:image->bitmap().makeCGImage().get() size:size]).get());
}

#pragma mark - WKTextFinderMatch callbacks

- (void)getImageForMatchResult:(id <NSTextFinderAsynchronousDocumentFindMatch>)findMatch completionHandler:(void (^)(NSImage *generatedImage))completionHandler
{
    ASSERT([findMatch isKindOfClass:[WKTextFinderMatch class]]);

    WKTextFinderMatch *textFinderMatch = static_cast<WKTextFinderMatch *>(findMatch);

    auto copiedImageCallback = Block_copy(completionHandler);
    _imageReplyCallbacks.append([copiedImageCallback] (NSImage *image) {
        copiedImageCallback(image);
        Block_release(copiedImageCallback);
    });

    // FIXME: There is no guarantee that this will ever result in didGetImageForMatchResult
    // being called (and thus us calling our completion handler); we should harden this
    // against all of the early returns in FindController::getImageForFindMatch.
    _page->getImageForFindMatch(textFinderMatch.index);
}

@end

#endif // PLATFORM(MAC)
