/*
 * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2018 Apple Inc. All rights reserved.
 *
 * 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"

#include "AXObjectCache.h"
#include "ElementIterator.h"
#include "EventNames.h"
#include "EventSender.h"
#include "HTMLSlotElement.h"
#include "HTMLSummaryElement.h"
#include "LocalizedStrings.h"
#include "MouseEvent.h"
#include "RenderBlockFlow.h"
#include "ShadowRoot.h"
#include "SlotAssignment.h"
#include "Text.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/NeverDestroyed.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLDetailsElement);

using namespace HTMLNames;

static DetailEventSender& detailToggleEventSender()
{
    static NeverDestroyed<DetailEventSender> sharedToggleEventSender(eventNames().toggleEvent);
    return sharedToggleEventSender;
}

static const AtomicString& summarySlotName()
{
    static NeverDestroyed<AtomicString> summarySlot("summarySlot");
    return summarySlot;
}

class DetailsSlotAssignment final : public SlotAssignment {
private:
    void hostChildElementDidChange(const Element&, ShadowRoot&) override;
    const AtomicString& slotNameForHostChild(const Node&) const override;
};

void DetailsSlotAssignment::hostChildElementDidChange(const Element& childElement, ShadowRoot& shadowRoot)
{
    if (is<HTMLSummaryElement>(childElement)) {
        // Don't check whether this is the first summary element
        // since we don't know the answer when this function is called inside Element::removedFrom.
        didChangeSlot(summarySlotName(), shadowRoot);
    } else
        didChangeSlot(SlotAssignment::defaultSlotName(), shadowRoot);
}

const AtomicString& DetailsSlotAssignment::slotNameForHostChild(const Node& child) const
{
    auto& parent = *child.parentNode();
    ASSERT(is<HTMLDetailsElement>(parent));
    auto& details = downcast<HTMLDetailsElement>(parent);

    // The first summary child gets assigned to the summary slot.
    if (is<HTMLSummaryElement>(child)) {
        if (&child == childrenOfType<HTMLSummaryElement>(details).first())
            return summarySlotName();
    }
    return SlotAssignment::defaultSlotName();
}

Ref<HTMLDetailsElement> HTMLDetailsElement::create(const QualifiedName& tagName, Document& document)
{
    auto details = adoptRef(*new HTMLDetailsElement(tagName, document));
    details->addShadowRoot(ShadowRoot::create(document, std::make_unique<DetailsSlotAssignment>()));
    return details;
}

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

HTMLDetailsElement::~HTMLDetailsElement()
{
    detailToggleEventSender().cancelEvent(*this);
}

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

void HTMLDetailsElement::didAddUserAgentShadowRoot(ShadowRoot& root)
{
    auto summarySlot = HTMLSlotElement::create(slotTag, document());
    summarySlot->setAttributeWithoutSynchronization(nameAttr, summarySlotName());
    m_summarySlot = summarySlot.ptr();

    auto defaultSummary = HTMLSummaryElement::create(summaryTag, document());
    defaultSummary->appendChild(Text::create(document(), defaultDetailsSummaryText()));
    m_defaultSummary = defaultSummary.ptr();

    summarySlot->appendChild(defaultSummary);
    root.appendChild(summarySlot);

    m_defaultSlot = HTMLSlotElement::create(slotTag, document());
    ASSERT(!m_isOpen);
}

bool HTMLDetailsElement::isActiveSummary(const HTMLSummaryElement& summary) const
{
    if (!m_summarySlot->assignedNodes())
        return &summary == m_defaultSummary;

    if (summary.parentNode() != this)
        return false;

    auto slot = makeRefPtr(shadowRoot()->findAssignedSlot(summary));
    if (!slot)
        return false;
    return slot == m_summarySlot;
}

void HTMLDetailsElement::dispatchPendingEvent(DetailEventSender* eventSender)
{
    ASSERT_UNUSED(eventSender, eventSender == &detailToggleEventSender());
    dispatchEvent(Event::create(eventNames().toggleEvent, false, false));
}

void HTMLDetailsElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    if (name == openAttr) {
        bool oldValue = m_isOpen;
        m_isOpen = !value.isNull();
        if (oldValue != m_isOpen) {
            auto root = makeRefPtr(shadowRoot());
            ASSERT(root);
            if (m_isOpen)
                root->appendChild(*m_defaultSlot);
            else
                root->removeChild(*m_defaultSlot);

            // https://html.spec.whatwg.org/#details-notification-task-steps.
            detailToggleEventSender().cancelEvent(*this);
            detailToggleEventSender().dispatchEventSoon(*this);
        }
    } else
        HTMLElement::parseAttribute(name, value);
}


void HTMLDetailsElement::toggleOpen()
{
    setAttributeWithoutSynchronization(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);
}

}
