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

#if PLATFORM(IOS_FAMILY)

#import "UIKitSPI.h"
#import "WKContentView.h"
#import "WKWebViewContentProvider.h"
#import <WebCore/LocalizedStrings.h>
#import <wtf/RetainPtr.h>
#import <wtf/text/WTFString.h>

const CGFloat passwordEntryFieldPadding = 10;

@interface WKPasswordView () <UIDocumentPasswordViewDelegate>
@end

@implementation WKPasswordView {
    RetainPtr<NSString> _documentName;
    RetainPtr<UIScrollView> _scrollView;
    RetainPtr<UIDocumentPasswordView> _passwordView;
    CGFloat _savedMinimumZoomScale;
    CGFloat _savedMaximumZoomScale;
    CGFloat _savedZoomScale;
    CGSize _savedContentSize;
    RetainPtr<UIColor> _savedBackgroundColor;
}

- (instancetype)initWithFrame:(CGRect)frame documentName:(NSString *)documentName
{
    self = [super initWithFrame:frame];
    if (!self)
        return nil;

    _documentName = adoptNS([documentName copy]);
    _passwordView = adoptNS([[UIDocumentPasswordView alloc] initWithDocumentName:_documentName.get()]);
    [_passwordView setFrame:self.bounds];
    [_passwordView setPasswordDelegate:self];
    [_passwordView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];

    self.autoresizesSubviews = YES;
    [self addSubview:_passwordView.get()];

    return self;
}

- (void)dealloc
{
    [_userDidEnterPassword release];
    [super dealloc];
}

- (NSString *)documentName
{
    return _documentName.get();
}

- (void)layoutSubviews
{
    if (_scrollView)
        [_scrollView setContentSize:self.frame.size];
}

- (void)showInScrollView:(UIScrollView *)scrollView
{
    _scrollView = scrollView;

    _savedMinimumZoomScale = [_scrollView minimumZoomScale];
    _savedMaximumZoomScale = [_scrollView maximumZoomScale];
    _savedZoomScale = [_scrollView zoomScale];
    _savedContentSize = [_scrollView contentSize];
    _savedBackgroundColor = [_scrollView backgroundColor];

    [_scrollView setMinimumZoomScale:1];
    [_scrollView setMaximumZoomScale:1];
    [_scrollView setZoomScale:1];
    [_scrollView setContentSize:self.frame.size];

#if HAVE(OS_DARK_MODE_SUPPORT)
    [_scrollView setBackgroundColor:UIColor.systemGroupedBackgroundColor];
#else
    [_scrollView setBackgroundColor:UIColor.groupTableViewBackgroundColor];
#endif

    [scrollView addSubview:self];
}

- (void)hide
{
    [_scrollView setMinimumZoomScale:_savedMinimumZoomScale];
    [_scrollView setMaximumZoomScale:_savedMaximumZoomScale];
    [_scrollView setZoomScale:_savedZoomScale];
    [_scrollView setContentSize:_savedContentSize];
    [_scrollView setBackgroundColor:_savedBackgroundColor.get()];

    _scrollView = nil;
    _savedBackgroundColor = nil;

    [self removeFromSuperview];
}

- (void)showPasswordFailureAlert
{
    [[_passwordView passwordField] setText:@""];
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:WEB_UI_STRING("The document could not be opened with that password.", "document password failure alert message") message:@"" preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:WEB_UI_STRING_KEY("OK", "OK (document password failure alert)", "OK button label in document password failure alert") style:UIAlertActionStyleDefault handler:[](UIAlertAction *) { }];

    [alert addAction:defaultAction];

    [self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}

- (void)_keyboardDidShow:(NSNotification *)notification
{
    UITextField *passwordField = [_passwordView passwordField];
    if (!passwordField.isEditing)
        return;

    CGRect keyboardRect = [UIPeripheralHost visiblePeripheralFrame];
    if (CGRectIsEmpty(keyboardRect))
        return;

    UIWindow *window = [_scrollView window];
    keyboardRect = [window convertRect:keyboardRect fromWindow:nil];
    keyboardRect = [_scrollView convertRect:keyboardRect fromView:window];

    CGRect passwordFieldFrame = [passwordField convertRect:passwordField.bounds toView:_scrollView.get()];

    CGSize contentSize = [_passwordView bounds].size;
    contentSize.height += CGRectGetHeight(keyboardRect);
    [_scrollView setContentSize:contentSize];

    if (CGRectIntersectsRect(passwordFieldFrame, keyboardRect)) {
        CGFloat yDelta = CGRectGetMaxY(passwordFieldFrame) - CGRectGetMinY(keyboardRect);

        CGPoint contentOffset = [_scrollView contentOffset];
        contentOffset.y += yDelta + passwordEntryFieldPadding;

        [_scrollView setContentOffset:contentOffset animated:YES];
    }
}

#pragma mark UIDocumentPasswordViewDelegate

- (void)userDidEnterPassword:(NSString *)password forPasswordView:(UIDocumentPasswordView *)passwordView
{
    auto protectedSelf = retainPtr(self);
    if (_userDidEnterPassword)
        _userDidEnterPassword(password);
}

- (void)didBeginEditingPassword:(UITextField *)passwordField inView:(UIDocumentPasswordView *)passwordView
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}

- (void)didEndEditingPassword:(UITextField *)passwordField inView:(UIDocumentPasswordView *)passwordView
{
    [_scrollView setContentSize:[_passwordView frame].size];

    UIEdgeInsets contentInset = [_scrollView contentInset];
    [_scrollView setContentOffset:CGPointMake(-contentInset.left, -contentInset.top) animated:YES];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}

@end

#endif // PLATFORM(IOS_FAMILY)
