/*
 * Copyright (C) 2011 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER 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 "core/dom/shadow/ShadowRoot.h"

#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/ContentDistributor.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/InsertionPoint.h"
#include "core/editing/markup.h"
#include "core/platform/HistogramSupport.h"

namespace WebCore {

struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope, public DoublyLinkedListNode<ShadowRoot> {
    void* pointers[3];
    unsigned countersAndFlags[1];
};

COMPILE_ASSERT(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small);

enum ShadowRootUsageOriginType {
    ShadowRootUsageOriginWeb = 0,
    ShadowRootUsageOriginNotWeb,
    ShadowRootUsageOriginMax
};

ShadowRoot::ShadowRoot(Document* document, ShadowRootType type)
    : DocumentFragment(0, CreateShadowRoot)
    , TreeScope(this, document)
    , m_prev(0)
    , m_next(0)
    , m_numberOfStyles(0)
    , m_applyAuthorStyles(false)
    , m_resetStyleInheritance(false)
    , m_type(type)
    , m_registeredWithParentShadowRoot(false)
{
    ASSERT(document);
    ScriptWrappable::init(this);

    if (type == ShadowRoot::AuthorShadowRoot) {
        ShadowRootUsageOriginType usageType = document->url().protocolIsInHTTPFamily() ? ShadowRootUsageOriginWeb : ShadowRootUsageOriginNotWeb;
        HistogramSupport::histogramEnumeration("WebCore.ShadowRoot.constructor", usageType, ShadowRootUsageOriginMax);
    }
}

ShadowRoot::~ShadowRoot()
{
    ASSERT(!m_prev);
    ASSERT(!m_next);

    // We cannot let ContainerNode destructor call willBeDeletedFrom()
    // for this ShadowRoot instance because TreeScope destructor
    // clears Node::m_treeScope thus ContainerNode is no longer able
    // to access it Document reference after that.
    willBeDeletedFrom(documentInternal());

    // We must remove all of our children first before the TreeScope destructor
    // runs so we don't go through TreeScopeAdopter for each child with a
    // destructed tree scope in each descendant.
    removeDetachedChildren();

    // We must call clearRareData() here since a ShadowRoot class inherits TreeScope
    // as well as Node. See a comment on TreeScope.h for the reason.
    if (hasRareData())
        clearRareData();
}

void ShadowRoot::dispose()
{
    removeDetachedChildren();
}

ShadowRoot* ShadowRoot::bindingsOlderShadowRoot() const
{
    ShadowRoot* older = olderShadowRoot();
    while (older && !older->shouldExposeToBindings())
        older = older->olderShadowRoot();
    ASSERT(!older || older->shouldExposeToBindings());
    return older;
}

PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec)
{
    ec = DataCloneError;
    return 0;
}

String ShadowRoot::innerHTML() const
{
    return createMarkup(this, ChildrenOnly);
}

void ShadowRoot::setInnerHTML(const String& markup, ExceptionCode& ec)
{
    if (isOrphan()) {
        ec = InvalidAccessError;
        return;
    }

    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, ec))
        replaceChildrenWithFragment(this, fragment.release(), ec);
}

bool ShadowRoot::childTypeAllowed(NodeType type) const
{
    switch (type) {
    case ELEMENT_NODE:
    case PROCESSING_INSTRUCTION_NODE:
    case COMMENT_NODE:
    case TEXT_NODE:
    case CDATA_SECTION_NODE:
        return true;
    default:
        return false;
    }
}

void ShadowRoot::recalcStyle(StyleChange change)
{
    // ShadowRoot doesn't support custom callbacks.
    ASSERT(!hasCustomStyleCallbacks());

    StyleResolver* styleResolver = document()->styleResolver();
    styleResolver->pushParentShadowRoot(this);

    if (!attached()) {
        attach();
        // attach recalculates the style for all children. No need to do it twice.
        clearNeedsStyleRecalc();
        clearChildNeedsStyleRecalc();
        return;
    }

    // When we're set to lazyAttach we'll have a SubtreeStyleChange and we'll need
    // to promote the change to a Force for all our descendants so they get a
    // recalc and will attach.
    if (styleChangeType() == SubtreeStyleChange)
        change = Force;

    // FIXME: This doesn't handle :hover + div properly like Element::recalcStyle does.
    bool forceReattachOfAnyWhitespaceSibling = false;
    for (Node* child = firstChild(); child; child = child->nextSibling()) {
        bool didReattach = false;

        if (child->renderer())
            forceReattachOfAnyWhitespaceSibling = false;

        if (child->isTextNode()) {
            if (forceReattachOfAnyWhitespaceSibling && toText(child)->containsOnlyWhitespace())
                child->reattach();
            else
                didReattach = toText(child)->recalcTextStyle(change);
        } else if (child->isElementNode() && shouldRecalcStyle(change, child)) {
            didReattach = toElement(child)->recalcStyle(change);
        }

        forceReattachOfAnyWhitespaceSibling = didReattach || forceReattachOfAnyWhitespaceSibling;
    }

    styleResolver->popParentShadowRoot(this);
    clearNeedsStyleRecalc();
    clearChildNeedsStyleRecalc();
}

bool ShadowRoot::isActive() const
{
    for (ShadowRoot* shadowRoot = youngerShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot())
        if (!shadowRoot->containsShadowElements())
            return false;
    return true;
}

void ShadowRoot::setApplyAuthorStyles(bool value)
{
    if (isOrphan())
        return;

    if (m_applyAuthorStyles == value)
        return;

    m_applyAuthorStyles = value;
    if (!isActive())
        return;

    setNeedsStyleRecalc();
}

void ShadowRoot::setResetStyleInheritance(bool value)
{
    if (isOrphan())
        return;

    if (value == m_resetStyleInheritance)
        return;

    m_resetStyleInheritance = value;
    if (!isActive())
        return;

    setNeedsStyleRecalc();
}

void ShadowRoot::attach(const AttachContext& context)
{
    StyleResolver* styleResolver = document()->styleResolver();
    styleResolver->pushParentShadowRoot(this);
    DocumentFragment::attach(context);
    styleResolver->popParentShadowRoot(this);
}

Node::InsertionNotificationRequest ShadowRoot::insertedInto(ContainerNode* insertionPoint)
{
    DocumentFragment::insertedInto(insertionPoint);

    if (!insertionPoint->inDocument() || !isOldest())
        return InsertionDone;

    // FIXME: When parsing <video controls>, insertedInto() is called many times without invoking removedFrom.
    // For now, we check m_registeredWithParentShadowroot. We would like to ASSERT(!m_registeredShadowRoot) here.
    // https://bugs.webkit.org/show_bug.cig?id=101316
    if (m_registeredWithParentShadowRoot)
        return InsertionDone;

    if (ShadowRoot* root = host()->containingShadowRoot()) {
        root->ensureScopeDistribution()->registerElementShadow();
        m_registeredWithParentShadowRoot = true;
    }

    return InsertionDone;
}

void ShadowRoot::removedFrom(ContainerNode* insertionPoint)
{
    if (insertionPoint->inDocument() && m_registeredWithParentShadowRoot) {
        ShadowRoot* root = host()->containingShadowRoot();
        if (!root)
            root = insertionPoint->containingShadowRoot();

        if (root && root->scopeDistribution())
            root->scopeDistribution()->unregisterElementShadow();
        m_registeredWithParentShadowRoot = false;
    }

    DocumentFragment::removedFrom(insertionPoint);
}

void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
    if (isOrphan())
        return;

    ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
    owner()->invalidateDistribution();
}

void ShadowRoot::registerScopedHTMLStyleChild()
{
    ++m_numberOfStyles;
    setHasScopedHTMLStyleChild(true);
}

void ShadowRoot::unregisterScopedHTMLStyleChild()
{
    ASSERT(hasScopedHTMLStyleChild() && m_numberOfStyles > 0);
    --m_numberOfStyles;
    setHasScopedHTMLStyleChild(m_numberOfStyles > 0);
}

ScopeContentDistribution* ShadowRoot::ensureScopeDistribution()
{
    if (m_scopeDistribution)
        return m_scopeDistribution.get();

    m_scopeDistribution = adoptPtr(new ScopeContentDistribution);
    return m_scopeDistribution.get();
}

bool ShadowRoot::containsShadowElements() const
{
    return m_scopeDistribution ? m_scopeDistribution->hasShadowElementChildren() : 0;
}

bool ShadowRoot::containsContentElements() const
{
    return m_scopeDistribution ? m_scopeDistribution->hasContentElementChildren() : 0;
}

bool ShadowRoot::containsShadowRoots() const
{
    return m_scopeDistribution ? m_scopeDistribution->numberOfElementShadowChildren() : 0;
}

InsertionPoint* ShadowRoot::insertionPoint() const
{
    return m_scopeDistribution ? m_scopeDistribution->insertionPointAssignedTo() : 0;
}

}
