/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
 * Copyright (C) 2012 Google 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 "VisitedLinkState.h"

#include "ElementIterator.h"
#include "Frame.h"
#include "HTMLAnchorElement.h"
#include "Page.h"
#include "SVGAElement.h"
#include "SVGNames.h"
#include "VisitedLinkStore.h"
#include "XLinkNames.h"

namespace WebCore {

using namespace HTMLNames;

inline static const AtomicString* linkAttribute(const Element& element)
{
    if (!element.isLink())
        return nullptr;
    if (element.isHTMLElement())
        return &element.attributeWithoutSynchronization(HTMLNames::hrefAttr);
    if (element.isSVGElement())
        return &element.getAttribute(SVGNames::hrefAttr, XLinkNames::hrefAttr);
    return nullptr;
}

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

void VisitedLinkState::invalidateStyleForAllLinks()
{
    if (m_linksCheckedForVisitedState.isEmpty())
        return;
    for (auto& element : descendantsOfType<Element>(m_document)) {
        if (element.isLink())
            element.invalidateStyleForSubtree();
    }
}

inline static Optional<SharedStringHash> linkHashForElement(const Element& element)
{
    if (is<HTMLAnchorElement>(element))
        return downcast<HTMLAnchorElement>(element).visitedLinkHash();
    if (is<SVGAElement>(element))
        return downcast<SVGAElement>(element).visitedLinkHash();
    return WTF::nullopt;
}

void VisitedLinkState::invalidateStyleForLink(SharedStringHash linkHash)
{
    if (!m_linksCheckedForVisitedState.contains(linkHash))
        return;
    for (auto& element : descendantsOfType<Element>(m_document)) {
        if (element.isLink() && linkHashForElement(element) == linkHash)
            element.invalidateStyleForSubtree();
    }
}

InsideLink VisitedLinkState::determineLinkStateSlowCase(const Element& element)
{
    ASSERT(element.isLink());

    const AtomicString* attribute = linkAttribute(element);
    if (!attribute || attribute->isNull())
        return InsideLink::NotInside;

    auto hashIfFound = linkHashForElement(element);

    if (!hashIfFound)
        return attribute->isEmpty() ? InsideLink::InsideVisited : InsideLink::InsideUnvisited;

    auto hash = *hashIfFound;

    // An empty href (hash==0) refers to the document itself which is always visited. It is useful to check this explicitly so
    // that visited links can be tested in platform independent manner, without explicit support in the test harness.
    if (!hash)
        return InsideLink::InsideVisited;

    Frame* frame = element.document().frame();
    if (!frame)
        return InsideLink::InsideUnvisited;

    Page* page = frame->page();
    if (!page)
        return InsideLink::InsideUnvisited;

    m_linksCheckedForVisitedState.add(hash);

    if (!page->visitedLinkStore().isLinkVisited(*page, hash, element.document().baseURL(), *attribute))
        return InsideLink::InsideUnvisited;

    return InsideLink::InsideVisited;
}

} // namespace WebCore
