/*
 * Copyright (C) 2010 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 "MediaQueryMatcher.h"

#include "Document.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameView.h"
#include "Logging.h"
#include "MediaList.h"
#include "MediaQueryEvaluator.h"
#include "MediaQueryList.h"
#include "MediaQueryListEvent.h"
#include "MediaQueryParserContext.h"
#include "NodeRenderStyle.h"
#include "RenderElement.h"
#include "StyleResolver.h"
#include "StyleScope.h"
#include <wtf/text/TextStream.h>

namespace WebCore {

MediaQueryMatcher::MediaQueryMatcher(Document& document)
    : m_document(document)
{
}

MediaQueryMatcher::~MediaQueryMatcher() = default;

void MediaQueryMatcher::documentDestroyed()
{
    m_document = nullptr;
    auto mediaQueryLists = std::exchange(m_mediaQueryLists, { });
    for (auto& mediaQueryList : mediaQueryLists) {
        if (mediaQueryList)
            mediaQueryList->detachFromMatcher();
    }
}

String MediaQueryMatcher::mediaType() const
{
    if (!m_document || !m_document->frame() || !m_document->frame()->view())
        return String();

    return m_document->frame()->view()->mediaType();
}

std::unique_ptr<RenderStyle> MediaQueryMatcher::documentElementUserAgentStyle() const
{
    if (!m_document || !m_document->frame())
        return nullptr;

    auto* documentElement = m_document->documentElement();
    if (!documentElement)
        return nullptr;

    return m_document->styleScope().resolver().styleForElement(*documentElement, { m_document->renderStyle() }, RuleMatchingBehavior::MatchOnlyUserAgentRules).renderStyle;
}

bool MediaQueryMatcher::evaluate(const MediaQuerySet& media)
{
    auto style = documentElementUserAgentStyle();
    if (!style)
        return false;
    return MediaQueryEvaluator { mediaType(), *m_document, style.get() }.evaluate(media);
}

void MediaQueryMatcher::addMediaQueryList(MediaQueryList& list)
{
    ASSERT(!m_mediaQueryLists.contains(&list));
    m_mediaQueryLists.append(list);
}

void MediaQueryMatcher::removeMediaQueryList(MediaQueryList& list)
{
    m_mediaQueryLists.removeFirst(&list);
}

RefPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const String& query)
{
    if (!m_document)
        return nullptr;

    auto media = MediaQuerySet::create(query, MediaQueryParserContext(*m_document));
    reportMediaQueryWarningIfNeeded(m_document.get(), media.ptr());
    bool matches = evaluate(media.get());
    return MediaQueryList::create(*m_document, *this, WTFMove(media), matches);
}

void MediaQueryMatcher::evaluateAll()
{
    ASSERT(m_document);

    ++m_evaluationRound;

    auto style = documentElementUserAgentStyle();
    if (!style)
        return;

    LOG_WITH_STREAM(MediaQueries, stream << "MediaQueryMatcher::styleResolverChanged " << m_document->url());

    MediaQueryEvaluator evaluator { mediaType(), *m_document, style.get() };

    auto mediaQueryLists = m_mediaQueryLists;
    for (auto& list : mediaQueryLists) {
        if (!list)
            continue;
        bool notify;
        list->evaluate(evaluator, notify);
        if (notify) {
            if (m_document && m_document->quirks().shouldSilenceMediaQueryListChangeEvents())
                continue;

            list->dispatchEvent(MediaQueryListEvent::create(eventNames().changeEvent, list->media(), list->matches()));
        }
    }
}

} // namespace WebCore
