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


#include "config.h"
#include "EditingTestHarness.h"

#import "PlatformUtilities.h"
#import <WebKit/WKWebViewPrivate.h>

@implementation EditingTestHarness

- (instancetype)initWithWebView:(TestWKWebView *)webView
{
    if (self = [super init]) {
        _webView = webView;
        [_webView setUIDelegate:self];
        _editorStateHistory = adoptNS([[NSMutableArray alloc] init]);
    }
    return self;
}

- (void)dealloc
{
    if ([_webView UIDelegate] == self)
        [_webView setUIDelegate:nil];

    [super dealloc];
}

- (TestWKWebView *)webView
{
    return _webView.get();
}

- (NSDictionary *)latestEditorState
{
    return self.editorStateHistory.lastObject;
}

- (NSArray<NSDictionary *> *)editorStateHistory
{
    return _editorStateHistory.get();
}

- (void)insertParagraph
{
    [self insertParagraphAndExpectEditorStateWith:nil];
}

- (void)insertText:(NSString *)text
{
    [self insertText:text andExpectEditorStateWith:nil];
}

- (void)insertHTML:(NSString *)html
{
    [self insertHTML:html andExpectEditorStateWith:nil];
}

- (void)selectAll
{
    [self selectAllAndExpectEditorStateWith:nil];
}

- (void)deleteBackwards
{
    [self deleteBackwardAndExpectEditorStateWith:nil];
}

- (void)moveBackward
{
    [self moveBackwardAndExpectEditorStateWith:nil];
}

- (void)moveForward
{
    [self moveForwardAndExpectEditorStateWith:nil];
}

- (void)insertText:(NSString *)text andExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"InsertText" argument:text expectEntries:entries];
}

- (void)insertHTML:(NSString *)html andExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"InsertHTML" argument:html expectEntries:entries];
}

- (void)selectAllAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"SelectAll" argument:nil expectEntries:entries];
}

- (void)moveBackwardAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"MoveBackward" argument:nil expectEntries:entries];
}

- (void)moveWordBackwardAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"MoveWordBackward" argument:nil expectEntries:entries];
}

- (void)moveForwardAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"MoveForward" argument:nil expectEntries:entries];
}

- (void)toggleBold
{
    [self _execCommand:@"ToggleBold" argument:nil expectEntries:nil];
}

- (void)toggleItalic
{
    [self _execCommand:@"ToggleItalic" argument:nil expectEntries:nil];
}

- (void)toggleUnderline
{
    [self _execCommand:@"ToggleUnderline" argument:nil expectEntries:nil];
}

- (void)setForegroundColor:(NSString *)colorAsString
{
    [self _execCommand:@"ForeColor" argument:colorAsString expectEntries:nil];
}

- (void)alignJustifiedAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"AlignJustified" argument:nil expectEntries:entries];
}

- (void)alignLeftAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"AlignLeft" argument:nil expectEntries:entries];
}

- (void)alignCenterAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"AlignCenter" argument:nil expectEntries:entries];
}

- (void)alignRightAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"AlignRight" argument:nil expectEntries:entries];
}

- (void)insertParagraphAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"InsertParagraph" argument:nil expectEntries:entries];
}

- (void)deleteBackwardAndExpectEditorStateWith:(NSDictionary<NSString *, id> *)entries
{
    [self _execCommand:@"DeleteBackward" argument:nil expectEntries:entries];
}

- (void)_execCommand:(NSString *)command argument:(NSString *)argument expectEntries:(NSDictionary<NSString *, id> *)entries
{
    __block BOOL result = false;
    __block bool done = false;
    [_webView _executeEditCommand:command argument:argument completion:^(BOOL success) {
        result = success;
        done = true;
    }];
    TestWebKitAPI::Util::run(&done);

    EXPECT_TRUE(result);
    if (!result)
        NSLog(@"Failed to execute editing command: ('%@', '%@')", command, argument ?: @"");

    const NSTimeInterval loggingTimeout = 3;
    auto startTime = retainPtr([NSDate date]);
    BOOL hasLoggedWarning = NO;
    BOOL containsEntries;
    do {
        [_webView waitForNextPresentationUpdate];
        containsEntries = [self latestEditorStateContains:entries];
        if (!hasLoggedWarning && [[NSDate date] timeIntervalSinceDate:startTime.get()] > loggingTimeout) {
            NSLog(@"Expected %@ to contain %@", self.latestEditorState, entries);
            hasLoggedWarning = YES;
        }
    } while (!containsEntries);
}

- (BOOL)latestEditorStateContains:(NSDictionary<NSString *, id> *)entries
{
    NSDictionary *latestEditorState = self.latestEditorState;
    for (NSString *key in entries) {
        if (![latestEditorState[key] isEqual:entries[key]])
            return NO;
    }
    return latestEditorState.count || !entries.count;
}

#pragma mark - WKUIDelegatePrivate

- (void)_webView:(WKWebView *)webView editorStateDidChange:(NSDictionary *)editorState
{
    if (![editorState[@"post-layout-data"] boolValue])
        return;

    if (![self.latestEditorState isEqualToDictionary:editorState])
        [_editorStateHistory addObject:editorState];
}

@end
