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

#include "config.h"
#include "YouTubePluginReplacement.h"

#include "HTMLIFrameElement.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "HTMLPlugInElement.h"
#include "RenderElement.h"
#include "Settings.h"
#include "ShadowRoot.h"
#include "YouTubeEmbedShadowElement.h"
#include <wtf/text/StringBuilder.h>

namespace WebCore {

void YouTubePluginReplacement::registerPluginReplacement(PluginReplacementRegistrar registrar)
{
    registrar(ReplacementPlugin(create, supportsMimeType, supportsFileExtension, supportsURL, isEnabledBySettings));
}

Ref<PluginReplacement> YouTubePluginReplacement::create(HTMLPlugInElement& plugin, const Vector<String>& paramNames, const Vector<String>& paramValues)
{
    return adoptRef(*new YouTubePluginReplacement(plugin, paramNames, paramValues));
}

bool YouTubePluginReplacement::supportsMimeType(const String& mimeType)
{
    return equalLettersIgnoringASCIICase(mimeType, "application/x-shockwave-flash")
        || equalLettersIgnoringASCIICase(mimeType, "application/futuresplash");
}

bool YouTubePluginReplacement::supportsFileExtension(const String& extension)
{
    return equalLettersIgnoringASCIICase(extension, "spl") || equalLettersIgnoringASCIICase(extension, "swf");
}

YouTubePluginReplacement::YouTubePluginReplacement(HTMLPlugInElement& plugin, const Vector<String>& paramNames, const Vector<String>& paramValues)
    : m_parentElement(&plugin)
{
    ASSERT(paramNames.size() == paramValues.size());
    for (size_t i = 0; i < paramNames.size(); ++i)
        m_attributes.add(paramNames[i], paramValues[i]);
}

RenderPtr<RenderElement> YouTubePluginReplacement::createElementRenderer(HTMLPlugInElement& plugin, RenderStyle&& style, const RenderTreePosition& insertionPosition)
{
    ASSERT_UNUSED(plugin, m_parentElement == &plugin);

    if (!m_embedShadowElement)
        return nullptr;
    
    return m_embedShadowElement->createElementRenderer(WTFMove(style), insertionPosition);
}

bool YouTubePluginReplacement::installReplacement(ShadowRoot& root)
{
    m_embedShadowElement = YouTubeEmbedShadowElement::create(m_parentElement->document());

    root.appendChild(*m_embedShadowElement);

    auto iframeElement = HTMLIFrameElement::create(HTMLNames::iframeTag, m_parentElement->document());
    if (m_attributes.contains("width"))
        iframeElement->setAttributeWithoutSynchronization(HTMLNames::widthAttr, AtomicString("100%", AtomicString::ConstructFromLiteral));
    
    const auto& heightValue = m_attributes.find("height");
    if (heightValue != m_attributes.end()) {
        iframeElement->setAttribute(HTMLNames::styleAttr, AtomicString("max-height: 100%", AtomicString::ConstructFromLiteral));
        iframeElement->setAttributeWithoutSynchronization(HTMLNames::heightAttr, heightValue->value);
    }

    iframeElement->setAttributeWithoutSynchronization(HTMLNames::srcAttr, youTubeURL(m_attributes.get("src")));
    iframeElement->setAttributeWithoutSynchronization(HTMLNames::frameborderAttr, AtomicString("0", AtomicString::ConstructFromLiteral));
    
    // Disable frame flattening for this iframe.
    iframeElement->setAttributeWithoutSynchronization(HTMLNames::scrollingAttr, AtomicString("no", AtomicString::ConstructFromLiteral));
    m_embedShadowElement->appendChild(iframeElement);

    return true;
}
    
static inline URL createYouTubeURL(const String& videoID, const String& timeID)
{
    ASSERT(!videoID.isEmpty());
    ASSERT(videoID != "/");
    
    URL result(URL(), "youtube:" + videoID);
    if (!timeID.isEmpty())
        result.setQuery("t=" + timeID);
    
    return result;
}
    
static YouTubePluginReplacement::KeyValueMap queryKeysAndValues(const String& queryString)
{
    YouTubePluginReplacement::KeyValueMap queryDictionary;
    
    size_t queryLength = queryString.length();
    if (!queryLength)
        return queryDictionary;
    
    size_t equalSearchLocation = 0;
    size_t equalSearchLength = queryLength;
    
    while (equalSearchLocation < queryLength - 1 && equalSearchLength) {
        
        // Search for "=".
        size_t equalLocation = queryString.find('=', equalSearchLocation);
        if (equalLocation == notFound)
            break;
        
        size_t indexAfterEqual = equalLocation + 1;
        if (indexAfterEqual > queryLength - 1)
            break;
        
        // Get the key before the "=".
        size_t keyLocation = equalSearchLocation;
        size_t keyLength = equalLocation - equalSearchLocation;
        
        // Seach for the ampersand.
        size_t ampersandLocation = queryString.find('&', indexAfterEqual);
        
        // Get the value after the "=", before the ampersand.
        size_t valueLocation = indexAfterEqual;
        size_t valueLength;
        if (ampersandLocation != notFound)
            valueLength = ampersandLocation - indexAfterEqual;
        else
            valueLength = queryLength - indexAfterEqual;
        
        // Save the key and the value.
        if (keyLength && valueLength) {
            String key = queryString.substring(keyLocation, keyLength).convertToASCIILowercase();
            String value = queryString.substring(valueLocation, valueLength);
            value.replace('+', ' ');

            if (!key.isEmpty() && !value.isEmpty())
                queryDictionary.add(key, value);
        }
        
        if (ampersandLocation == notFound)
            break;
        
        // Continue searching after the ampersand.
        size_t indexAfterAmpersand = ampersandLocation + 1;
        equalSearchLocation = indexAfterAmpersand;
        equalSearchLength = queryLength - indexAfterAmpersand;
    }
    
    return queryDictionary;
}
    
static bool isYouTubeURL(const URL& url)
{
    auto hostName = url.host();
    return equalLettersIgnoringASCIICase(hostName, "m.youtube.com")
        || equalLettersIgnoringASCIICase(hostName, "youtu.be")
        || equalLettersIgnoringASCIICase(hostName, "www.youtube.com")
        || equalLettersIgnoringASCIICase(hostName, "youtube.com")
        || equalLettersIgnoringASCIICase(hostName, "www.youtube-nocookie.com")
        || equalLettersIgnoringASCIICase(hostName, "youtube-nocookie.com");
}

static const String& valueForKey(const YouTubePluginReplacement::KeyValueMap& dictionary, const String& key)
{
    const auto& value = dictionary.find(key);
    if (value == dictionary.end())
        return emptyString();

    return value->value;
}

static URL processAndCreateYouTubeURL(const URL& url, bool& isYouTubeShortenedURL, String& outPathAfterFirstAmpersand)
{
    if (!url.protocolIsInHTTPFamily())
        return URL();

    // Bail out early if we aren't even on www.youtube.com or youtube.com.
    if (!isYouTubeURL(url))
        return URL();

    auto hostName = url.host();
    bool isYouTubeMobileWebAppURL = equalLettersIgnoringASCIICase(hostName, "m.youtube.com");
    isYouTubeShortenedURL = equalLettersIgnoringASCIICase(hostName, "youtu.be");

    // Short URL of the form: http://youtu.be/v1d301D
    if (isYouTubeShortenedURL) {
        String videoID = url.lastPathComponent();
        if (videoID.isEmpty() || videoID == "/")
            return URL();
        return createYouTubeURL(videoID, emptyString());
    }
    
    String path = url.path();
    String query = url.query();
    String fragment = url.fragmentIdentifier();
    
    // On the YouTube mobile web app, the path and query string are put into the
    // fragment so that one web page is only ever loaded (see <rdar://problem/9550639>).
    if (isYouTubeMobileWebAppURL) {
        size_t location = fragment.find('?');
        if (location == notFound) {
            path = fragment;
            query = emptyString();
        } else {
            path = fragment.substring(0, location);
            query = fragment.substring(location + 1);
        }
        fragment = emptyString();
    }
    
    if (equalLettersIgnoringASCIICase(path, "/watch")) {
        if (!query.isEmpty()) {
            const auto& queryDictionary = queryKeysAndValues(query);
            String videoID = valueForKey(queryDictionary, "v");
            
            if (!videoID.isEmpty()) {
                const auto& fragmentDictionary = queryKeysAndValues(url.fragmentIdentifier());
                String timeID = valueForKey(fragmentDictionary, "t");
                return createYouTubeURL(videoID, timeID);
            }
        }
        
        // May be a new-style link (see <rdar://problem/7733692>).
        if (fragment.startsWith('!')) {
            query = fragment.substring(1);
            
            if (!query.isEmpty()) {
                const auto& queryDictionary = queryKeysAndValues(query);
                String videoID = valueForKey(queryDictionary, "v");
                
                if (!videoID.isEmpty()) {
                    String timeID = valueForKey(queryDictionary, "t");
                    return createYouTubeURL(videoID, timeID);
                }
            }
        }
    } else if (startsWithLettersIgnoringASCIICase(path, "/v/") || startsWithLettersIgnoringASCIICase(path, "/e/")) {
        String lastPathComponent = url.lastPathComponent();
        String videoID;
        String pathAfterFirstAmpersand;

        size_t ampersandLocation = lastPathComponent.find('&');
        if (ampersandLocation != notFound) {
            // Some URLs we care about use & in place of ? for the first query parameter.
            videoID = lastPathComponent.substring(0, ampersandLocation);
            pathAfterFirstAmpersand = lastPathComponent.substring(ampersandLocation + 1, lastPathComponent.length() - ampersandLocation);
        } else
            videoID = lastPathComponent;

        if (!videoID.isEmpty()) {
            outPathAfterFirstAmpersand = pathAfterFirstAmpersand;
            return createYouTubeURL(videoID, emptyString());
        }
    }
    
    return URL();
}

String YouTubePluginReplacement::youTubeURL(const String& srcString)
{
    URL srcURL = m_parentElement->document().completeURL(stripLeadingAndTrailingHTMLSpaces(srcString));
    return youTubeURLFromAbsoluteURL(srcURL, srcString);
}

String YouTubePluginReplacement::youTubeURLFromAbsoluteURL(const URL& srcURL, const String& srcString)
{
    bool isYouTubeShortenedURL = false;
    String possibleMalformedQuery;
    URL youTubeURL = processAndCreateYouTubeURL(srcURL, isYouTubeShortenedURL, possibleMalformedQuery);
    if (srcURL.isEmpty() || youTubeURL.isEmpty())
        return srcString;

    // Transform the youtubeURL (youtube:VideoID) to iframe embed url which has the format: http://www.youtube.com/embed/VideoID
    const String& srcPath = srcURL.path();
    const String& videoID = youTubeURL.string().substring(youTubeURL.protocol().length() + 1);
    size_t locationOfVideoIDInPath = srcPath.find(videoID);

    size_t locationOfPathBeforeVideoID = notFound;
    if (locationOfVideoIDInPath != notFound) {
        ASSERT(locationOfVideoIDInPath);
    
        // From the original URL, we need to get the part before /path/VideoId.
        locationOfPathBeforeVideoID = srcString.find(srcPath.substring(0, locationOfVideoIDInPath));
    } else if (equalLettersIgnoringASCIICase(srcPath, "/watch")) {
        // From the original URL, we need to get the part before /watch/#!v=VideoID
        // FIXME: Shouldn't this be ASCII case-insensitive?
        locationOfPathBeforeVideoID = srcString.find("/watch");
    } else
        return srcString;

    ASSERT(locationOfPathBeforeVideoID != notFound);

    const String& srcURLPrefix = srcString.substring(0, locationOfPathBeforeVideoID);
    String query = srcURL.query();
    // If the URL has no query, use the possibly malformed query we found.
    if (query.isEmpty())
        query = possibleMalformedQuery;

    // Append the query string if it is valid.
    StringBuilder finalURL;
    if (isYouTubeShortenedURL)
        finalURL.appendLiteral("http://www.youtube.com");
    else
        finalURL.append(srcURLPrefix);
    finalURL.appendLiteral("/embed/");
    finalURL.append(videoID);
    if (!query.isEmpty()) {
        finalURL.append('?');
        finalURL.append(query);
    }
    return finalURL.toString();
}
    
bool YouTubePluginReplacement::supportsURL(const URL& url)
{
    return isYouTubeURL(url);
}

bool YouTubePluginReplacement::isEnabledBySettings(const Settings& settings)
{
    return settings.youTubeFlashPluginReplacementEnabled();
}
    
}
