/*
 * Copyright (C) 2006-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. ``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 "Editor.h"

#import "ArchiveResource.h"
#import "CSSValueList.h"
#import "CSSValuePool.h"
#import "CachedResourceLoader.h"
#import "ColorMac.h"
#import "DocumentFragment.h"
#import "DocumentLoader.h"
#import "Editing.h"
#import "EditingStyle.h"
#import "EditorClient.h"
#import "ElementInlines.h"
#import "FontAttributes.h"
#import "FontCascade.h"
#import "Frame.h"
#import "FrameLoader.h"
#import "FrameSelection.h"
#import "HTMLAttachmentElement.h"
#import "HTMLConverter.h"
#import "HTMLImageElement.h"
#import "HTMLSpanElement.h"
#import "ImageOverlay.h"
#import "LegacyNSPasteboardTypes.h"
#import "LegacyWebArchive.h"
#import "Page.h"
#import "PagePasteboardContext.h"
#import "Pasteboard.h"
#import "PasteboardStrategy.h"
#import "PlatformStrategies.h"
#import "RenderElement.h"
#import "RenderStyle.h"
#import "Settings.h"
#import "SystemSoundManager.h"
#import "Text.h"
#import "UTIUtilities.h"
#import "WebContentReader.h"
#import "markup.h"
#import <pal/spi/cocoa/NSAttributedStringSPI.h>
#import <wtf/BlockObjCExceptions.h>
#import <wtf/cocoa/NSURLExtras.h>

namespace WebCore {

static RefPtr<SharedBuffer> archivedDataForAttributedString(NSAttributedString *attributedString)
{
    if (!attributedString.length)
        return nullptr;

    return SharedBuffer::create([NSKeyedArchiver archivedDataWithRootObject:attributedString requiringSecureCoding:YES error:nullptr]);
}

String Editor::selectionInHTMLFormat()
{
    if (ImageOverlay::isInsideOverlay(m_document.selection().selection()))
        return { };
    return serializePreservingVisualAppearance(m_document.selection().selection(), ResolveURLs::YesExcludingLocalFileURLsForPrivacy, SerializeComposedTree::Yes);
}

#if ENABLE(ATTACHMENT_ELEMENT)

void Editor::getPasteboardTypesAndDataForAttachment(Element& element, Vector<String>& outTypes, Vector<RefPtr<SharedBuffer>>& outData)
{
    auto elementRange = makeRangeSelectingNode(element);
    client()->getClientPasteboardData(elementRange, outTypes, outData);

    outTypes.append(PasteboardCustomData::cocoaType());
    outData.append(PasteboardCustomData { element.document().originIdentifierForPasteboard(), { } }.createSharedBuffer());

    if (elementRange) {
        if (auto archive = LegacyWebArchive::create(*elementRange)) {
            if (auto data = archive->rawDataRepresentation()) {
                outTypes.append(WebArchivePboardType);
                outData.append(SharedBuffer::create(data.get()));
            }
        }
    }
}

#endif

static RetainPtr<NSAttributedString> selectionInImageOverlayAsAttributedString(const VisibleSelection& selection)
{
#if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS)
    auto* page = selection.document()->page();
    if (!page)
        return nil;

    RefPtr hostElement = dynamicDowncast<HTMLElement>(selection.start().containerNode()->shadowHost());
    if (!hostElement) {
        ASSERT_NOT_REACHED();
        return nil;
    }

    auto cachedResult = page->cachedTextRecognitionResult(*hostElement);
    if (!cachedResult)
        return nil;

    auto characterRange = valueOrDefault(ImageOverlay::characterRange(selection));
    if (!characterRange.length)
        return nil;

    auto string = stringForRange(*cachedResult, characterRange);
    __block bool hasAnyAttributes = false;
    [string enumerateAttributesInRange:NSMakeRange(0, [string length]) options:0 usingBlock:^(NSDictionary *attributes, NSRange, BOOL *stop) {
        if (attributes.count) {
            hasAnyAttributes = true;
            *stop = YES;
        }
    }];

    if (!hasAnyAttributes)
        return nil;

    return string;
#else
    UNUSED_PARAM(selection);
    return nil;
#endif
}

static RetainPtr<NSAttributedString> selectionAsAttributedString(const Document& document)
{
    auto selection = document.selection().selection();
    if (ImageOverlay::isInsideOverlay(selection))
        return selectionInImageOverlayAsAttributedString(selection);
    auto range = selection.firstRange();
    return range ? attributedString(*range).string : adoptNS([[NSAttributedString alloc] init]);
}

void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
{
    auto string = selectionAsAttributedString(m_document);

    PasteboardWebContent content;
    content.contentOrigin = m_document.originIdentifierForPasteboard();
    content.canSmartCopyOrDelete = canSmartCopyOrDelete();
    if (!pasteboard.isStatic()) {
        content.dataInWebArchiveFormat = selectionInWebArchiveFormat();
        content.dataInRTFDFormat = [string containsAttachments] ? dataInRTFDFormat(string.get()) : nullptr;
        content.dataInRTFFormat = dataInRTFFormat(string.get());
        content.dataInAttributedStringFormat = archivedDataForAttributedString(string.get());
        client()->getClientPasteboardData(selectedRange(), content.clientTypes, content.clientData);
    }
    content.dataInHTMLFormat = selectionInHTMLFormat();
    content.dataInStringFormat = stringSelectionForPasteboardWithImageAltText();

    pasteboard.write(content);
}

void Editor::writeSelection(PasteboardWriterData& pasteboardWriterData)
{
    auto string = selectionAsAttributedString(m_document);

    PasteboardWriterData::WebContent webContent;
    webContent.contentOrigin = m_document.originIdentifierForPasteboard();
    webContent.canSmartCopyOrDelete = canSmartCopyOrDelete();
    webContent.dataInWebArchiveFormat = selectionInWebArchiveFormat();
    webContent.dataInRTFDFormat = [string containsAttachments] ? dataInRTFDFormat(string.get()) : nullptr;
    webContent.dataInRTFFormat = dataInRTFFormat(string.get());
    webContent.dataInAttributedStringFormat = archivedDataForAttributedString(string.get());
    webContent.dataInHTMLFormat = selectionInHTMLFormat();
    webContent.dataInStringFormat = stringSelectionForPasteboardWithImageAltText();
    client()->getClientPasteboardData(selectedRange(), webContent.clientTypes, webContent.clientData);

    pasteboardWriterData.setWebContent(WTFMove(webContent));
}

RefPtr<SharedBuffer> Editor::selectionInWebArchiveFormat()
{
    if (ImageOverlay::isInsideOverlay(m_document.selection().selection()))
        return nullptr;
    auto archive = LegacyWebArchive::createFromSelection(m_document.frame());
    if (!archive)
        return nullptr;
    return SharedBuffer::create(archive->rawDataRepresentation().get());
}

// FIXME: Makes no sense that selectedTextForDataTransfer always includes alt text, but stringSelectionForPasteboard does not.
// This was left in a bad state when selectedTextForDataTransfer was added. Need to look over clients and fix this.
String Editor::stringSelectionForPasteboard()
{
    if (!canCopy())
        return emptyString();
    return makeStringByReplacingAll(selectedText(), noBreakSpace, ' ');
}

String Editor::stringSelectionForPasteboardWithImageAltText()
{
    if (!canCopy())
        return emptyString();
    return makeStringByReplacingAll(selectedTextForDataTransfer(), noBreakSpace, ' ');
}

void Editor::replaceSelectionWithAttributedString(NSAttributedString *attributedString, MailBlockquoteHandling mailBlockquoteHandling)
{
    if (m_document.selection().isNone())
        return;

    if (m_document.selection().selection().isContentRichlyEditable()) {
        if (auto fragment = createFragmentAndAddResources(*m_document.frame(), attributedString)) {
            if (shouldInsertFragment(*fragment, selectedRange(), EditorInsertAction::Pasted))
                pasteAsFragment(fragment.releaseNonNull(), false, false, mailBlockquoteHandling);
        }
    } else {
        String text = attributedString.string;
        if (shouldInsertText(text, selectedRange(), EditorInsertAction::Pasted))
            pasteAsPlainText(text, false);
    }
}

String Editor::userVisibleString(const URL& url)
{
    return WTF::userVisibleString(url);
}

RefPtr<SharedBuffer> Editor::dataInRTFDFormat(NSAttributedString *string)
{
    NSUInteger length = string.length;
    if (!length)
        return nullptr;

    BEGIN_BLOCK_OBJC_EXCEPTIONS
    return SharedBuffer::create([string RTFDFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
    END_BLOCK_OBJC_EXCEPTIONS

    return nullptr;
}

RefPtr<SharedBuffer> Editor::dataInRTFFormat(NSAttributedString *string)
{
    NSUInteger length = string.length;
    if (!length)
        return nullptr;

    BEGIN_BLOCK_OBJC_EXCEPTIONS
    return SharedBuffer::create([string RTFFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
    END_BLOCK_OBJC_EXCEPTIONS

    return nullptr;
}

// FIXME: Should give this function a name that makes it clear it adds resources to the document loader as a side effect.
// Or refactor so it does not do that.
RefPtr<DocumentFragment> Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange& context, bool allowPlainText, bool& chosePlainText)
{
    WebContentReader reader(*m_document.frame(), context, allowPlainText);
    pasteboard.read(reader);
    chosePlainText = reader.madeFragmentFromPlainText;
    return WTFMove(reader.fragment);
}

void Editor::takeFindStringFromSelection()
{
    if (!canCopyExcludingStandaloneImages()) {
        SystemSoundManager::singleton().systemBeep();
        return;
    }

    auto stringFromSelection = m_document.frame()->displayStringModifiedByEncoding(selectedTextForDataTransfer());
#if PLATFORM(MAC)
    Vector<String> types;
    types.append(String(legacyStringPasteboardType()));
    auto context = PagePasteboardContext::create(m_document.pageID());
    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    platformStrategies()->pasteboardStrategy()->setTypes(types, NSFindPboard, context.get());
    platformStrategies()->pasteboardStrategy()->setStringForType(WTFMove(stringFromSelection), legacyStringPasteboardType(), NSFindPboard, context.get());
    ALLOW_DEPRECATED_DECLARATIONS_END
#else
    if (auto* client = this->client()) {
        // Since the find pasteboard doesn't exist on iOS, WebKit maintains its own notion of the latest find string,
        // which SPI clients may respect when presenting find-in-page UI.
        client->updateStringForFind(stringFromSelection);
    }
#endif
}

String Editor::platformContentTypeForBlobType(const String& type) const
{
    auto utiType = UTIFromMIMEType(type);
    if (!utiType.isEmpty())
        return utiType;
    return type;
}

void Editor::readSelectionFromPasteboard(const String& pasteboardName)
{
    Pasteboard pasteboard(PagePasteboardContext::create(m_document.pageID()), pasteboardName);
    if (m_document.selection().selection().isContentRichlyEditable())
        pasteWithPasteboard(&pasteboard, { PasteOption::AllowPlainText });
    else
        pasteAsPlainTextWithPasteboard(pasteboard);
}

static void maybeCopyNodeAttributesToFragment(const Node& node, DocumentFragment& fragment)
{
    // This is only supported for single-Node fragments.
    RefPtr firstChild = fragment.firstChild();
    if (!firstChild || firstChild != fragment.lastChild())
        return;

    // And only supported for HTML elements.
    if (!node.isHTMLElement() || !firstChild->isHTMLElement())
        return;

    // And only if the source Element and destination Element have the same HTML tag name.
    Ref oldElement = downcast<HTMLElement>(node);
    Ref newElement = downcast<HTMLElement>(*firstChild);
    if (oldElement->localName() != newElement->localName())
        return;

    for (auto& attribute : oldElement->attributesIterator()) {
        if (newElement->hasAttribute(attribute.name()))
            continue;
        newElement->setAttribute(attribute.name(), attribute.value());
    }
}

void Editor::replaceNodeFromPasteboard(Node& node, const String& pasteboardName, EditAction action)
{
    if (node.document() != m_document)
        return;

    auto range = makeRangeSelectingNode(node);
    if (!range)
        return;

    Ref protectedDocument = m_document;
    m_document.selection().setSelection({ *range }, FrameSelection::DoNotSetFocus);

    Pasteboard pasteboard(PagePasteboardContext::create(m_document.pageID()), pasteboardName);
    if (!m_document.selection().selection().isContentRichlyEditable()) {
        pasteAsPlainTextWithPasteboard(pasteboard);
        return;
    }

#if PLATFORM(MAC)
    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    // FIXME: How can this hard-coded pasteboard name be right, given that the passed-in pasteboard has a name?
    // FIXME: We can also remove `setInsertionPasteboard` altogether once Mail compose on macOS no longer uses WebKitLegacy,
    // since it's only implemented for WebKitLegacy on macOS, and the only known client is Mail compose.
    client()->setInsertionPasteboard(NSGeneralPboard);
    ALLOW_DEPRECATED_DECLARATIONS_END
#endif

    bool chosePlainText;
    if (auto fragment = webContentFromPasteboard(pasteboard, *range, true, chosePlainText)) {
        maybeCopyNodeAttributesToFragment(node, *fragment);
        if (shouldInsertFragment(*fragment, *range, EditorInsertAction::Pasted))
            pasteAsFragment(fragment.releaseNonNull(), false, false, MailBlockquoteHandling::IgnoreBlockquote, action);
    }

#if PLATFORM(MAC)
    client()->setInsertionPasteboard({ });
#endif
}

}
