/*
 * 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 "MediaQueryList.h"

#include "EventNames.h"
#include <wtf/IsoMallocInlines.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(MediaQueryList);

MediaQueryList::MediaQueryList(Document& document, MediaQueryMatcher& matcher, Ref<MediaQuerySet>&& media, bool matches)
    : ActiveDOMObject(&document)
    , m_matcher(&matcher)
    , m_media(WTFMove(media))
    , m_evaluationRound(matcher.evaluationRound())
    , m_changeRound(m_evaluationRound - 1) // Any value that is not the same as m_evaluationRound would do.
    , m_matches(matches)
{
    matcher.addMediaQueryList(*this);
}

Ref<MediaQueryList> MediaQueryList::create(Document& document, MediaQueryMatcher& matcher, Ref<MediaQuerySet>&& media, bool matches)
{
    auto list = adoptRef(*new MediaQueryList(document, matcher, WTFMove(media), matches));
    list->suspendIfNeeded();
    return list;
}

MediaQueryList::~MediaQueryList()
{
    if (m_matcher)
        m_matcher->removeMediaQueryList(*this);
}

void MediaQueryList::detachFromMatcher()
{
    m_matcher = nullptr;
}

String MediaQueryList::media() const
{
    return m_media->mediaText();
}

void MediaQueryList::addListener(RefPtr<EventListener>&& listener)
{
    if (!listener)
        return;

    addEventListener(eventNames().changeEvent, listener.releaseNonNull());
}

void MediaQueryList::removeListener(RefPtr<EventListener>&& listener)
{
    if (!listener)
        return;

    removeEventListener(eventNames().changeEvent, *listener);
}

void MediaQueryList::evaluate(MediaQueryEvaluator& evaluator, bool& notificationNeeded)
{
    if (!m_matcher) {
        notificationNeeded = false;
        return;
    }

    if (m_evaluationRound != m_matcher->evaluationRound())
        setMatches(evaluator.evaluate(m_media.get()));
    notificationNeeded = m_changeRound == m_matcher->evaluationRound();
}

void MediaQueryList::setMatches(bool newValue)
{
    ASSERT(m_matcher);
    m_evaluationRound = m_matcher->evaluationRound();

    if (newValue == m_matches)
        return;

    m_matches = newValue;
    m_changeRound = m_evaluationRound;
}

bool MediaQueryList::matches()
{
    if (m_matcher && m_evaluationRound != m_matcher->evaluationRound())
        setMatches(m_matcher->evaluate(m_media.get()));
    return m_matches;
}

void MediaQueryList::eventListenersDidChange()
{
    m_hasChangeEventListener = hasEventListeners(eventNames().changeEvent);
}

const char* MediaQueryList::activeDOMObjectName() const
{
    return "MediaQueryList";
}

bool MediaQueryList::virtualHasPendingActivity() const
{
    return m_hasChangeEventListener && m_matcher;
}

}
