/*
 * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "HTMLDetailsElement.h"

#if ENABLE(DETAILS_ELEMENT)
#include "AXObjectCache.h"
#include "ElementIterator.h"
#include "HTMLSummaryElement.h"
#include "InsertionPoint.h"
#include "LocalizedStrings.h"
#include "MouseEvent.h"
#include "RenderBlockFlow.h"
#include "Text.h"

namespace WebCore {

using namespace HTMLNames;

static const AtomicString& summaryQuerySelector()
{
    DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, selector, ("summary:first-of-type", AtomicString::ConstructFromLiteral));
    return selector;
};

class DetailsContentElement final : public InsertionPoint {
public:
    static Ref<DetailsContentElement> create(Document&);

private:
    DetailsContentElement(Document& document)
        : InsertionPoint(webkitShadowContentTag, document)
    {
    }

    virtual MatchType matchTypeFor(Node* node) const override
    {
        if (node->isElementNode() && node == node->parentNode()->querySelector(summaryQuerySelector(), ASSERT_NO_EXCEPTION))
            return NeverMatches;
        return AlwaysMatches;
    }
};

Ref<DetailsContentElement> DetailsContentElement::create(Document& document)
{
    return adoptRef(*new DetailsContentElement(document));
}

class DetailsSummaryElement final : public InsertionPoint {
public:
    static Ref<DetailsSummaryElement> create(Document&);

    Element* fallbackSummary()
    {
        ASSERT(firstChild() && firstChild()->hasTagName(summaryTag));
        return downcast<Element>(firstChild());
    }

private:
    DetailsSummaryElement(Document& document)
        : InsertionPoint(webkitShadowContentTag, document)
    {
    }

    virtual MatchType matchTypeFor(Node* node) const override
    {
        if (node->isElementNode() && node == node->parentNode()->querySelector(summaryQuerySelector(), ASSERT_NO_EXCEPTION))
            return AlwaysMatches;
        return NeverMatches;
    }
};

Ref<DetailsSummaryElement> DetailsSummaryElement::create(Document& document)
{
    RefPtr<HTMLSummaryElement> summary = HTMLSummaryElement::create(summaryTag, document);
    summary->appendChild(Text::create(document, defaultDetailsSummaryText()), ASSERT_NO_EXCEPTION);

    Ref<DetailsSummaryElement> detailsSummary = adoptRef(*new DetailsSummaryElement(document));
    detailsSummary->appendChild(summary);
    return detailsSummary;
}

Ref<HTMLDetailsElement> HTMLDetailsElement::create(const QualifiedName& tagName, Document& document)
{
    Ref<HTMLDetailsElement> details = adoptRef(*new HTMLDetailsElement(tagName, document));
    details->ensureUserAgentShadowRoot();
    return details;
}

HTMLDetailsElement::HTMLDetailsElement(const QualifiedName& tagName, Document& document)
    : HTMLElement(tagName, document)
    , m_isOpen(false)
{
    ASSERT(hasTagName(detailsTag));
}

RenderPtr<RenderElement> HTMLDetailsElement::createElementRenderer(Ref<RenderStyle>&& style, const RenderTreePosition&)
{
    return createRenderer<RenderBlockFlow>(*this, WTF::move(style));
}

void HTMLDetailsElement::didAddUserAgentShadowRoot(ShadowRoot* root)
{
    root->appendChild(DetailsSummaryElement::create(document()), ASSERT_NO_EXCEPTION);
    root->appendChild(DetailsContentElement::create(document()), ASSERT_NO_EXCEPTION);
}

const Element* HTMLDetailsElement::findMainSummary() const
{
    if (auto summary = childrenOfType<HTMLSummaryElement>(*this).first())
        return summary;

    return static_cast<DetailsSummaryElement*>(userAgentShadowRoot()->firstChild())->fallbackSummary();
}

void HTMLDetailsElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    if (name == openAttr) {
        bool oldValue = m_isOpen;
        m_isOpen = !value.isNull();
        if (oldValue != m_isOpen)
            setNeedsStyleRecalc(ReconstructRenderTree);
    } else
        HTMLElement::parseAttribute(name, value);
}

bool HTMLDetailsElement::childShouldCreateRenderer(const Node& child) const
{
    if (child.isPseudoElement())
        return HTMLElement::childShouldCreateRenderer(child);

    if (!hasShadowRootOrActiveInsertionPointParent(child))
        return false;

    if (m_isOpen)
        return HTMLElement::childShouldCreateRenderer(child);

    if (!child.hasTagName(summaryTag))
        return false;

    return &child == findMainSummary() && HTMLElement::childShouldCreateRenderer(child);
}

void HTMLDetailsElement::toggleOpen()
{
    setAttribute(openAttr, m_isOpen ? nullAtom : emptyAtom);

    // We need to post to the document because toggling this element will delete it.
    if (AXObjectCache* cache = document().existingAXObjectCache())
        cache->postNotification(nullptr, &document(), AXObjectCache::AXExpandedChanged);
}

}

#endif
