/*
 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2014 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.
 */

#pragma once

#include "CSSSelector.h"
#include <wtf/text/AtomStringHash.h>

namespace WebCore {

enum class CSSParserSelectorCombinator {
    Child,
    DescendantSpace,
    DirectAdjacent,
    IndirectAdjacent
};

class CSSParserSelector {
    WTF_MAKE_FAST_ALLOCATED;
public:
    static std::unique_ptr<CSSParserSelector> parsePseudoClassSelector(StringView);
    static std::unique_ptr<CSSParserSelector> parsePseudoElementSelector(StringView);
    static std::unique_ptr<CSSParserSelector> parsePagePseudoSelector(StringView);

    CSSParserSelector();
    explicit CSSParserSelector(const QualifiedName&);
    ~CSSParserSelector();

    std::unique_ptr<CSSSelector> releaseSelector() { return WTFMove(m_selector); }

    void setValue(const AtomString& value, bool matchLowerCase = false) { m_selector->setValue(value, matchLowerCase); }

    void setAttribute(const QualifiedName& value, bool convertToLowercase, CSSSelector::AttributeMatchType type) { m_selector->setAttribute(value, convertToLowercase, type); }
    
    void setArgument(const AtomString& value) { m_selector->setArgument(value); }
    void setNth(int a, int b) { m_selector->setNth(a, b); }
    void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); }
    void setRelation(CSSSelector::RelationType value) { m_selector->setRelation(value); }
    void setForPage() { m_selector->setForPage(); }

    CSSSelector::Match match() const { return m_selector->match(); }
    CSSSelector::PseudoElementType pseudoElementType() const { return m_selector->pseudoElementType(); }
    const CSSSelectorList* selectorList() const { return m_selector->selectorList(); }
    
    void setPseudoElementType(CSSSelector::PseudoElementType type) { m_selector->setPseudoElementType(type); }

    void adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>&&);
    void setArgumentList(std::unique_ptr<Vector<AtomString>>);
    void setSelectorList(std::unique_ptr<CSSSelectorList>);

    CSSSelector::PseudoClassType pseudoClassType() const { return m_selector->pseudoClassType(); }
    bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); }

    bool isPseudoElementCueFunction() const;

    bool hasShadowDescendant() const;
    bool matchesPseudoElement() const;

    bool isHostPseudoSelector() const;

    // FIXME-NEWPARSER: "slotted" was removed here for now, since it leads to a combinator
    // connection of ShadowDescendant, and the current shadow DOM code doesn't expect this. When
    // we do fix this issue, make sure to patch the namespace prependTag code to remove the slotted
    // special case, since it will be covered by this function once again.
    bool needsImplicitShadowCombinatorForMatching() const;

    CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
    void setTagHistory(std::unique_ptr<CSSParserSelector> selector) { m_tagHistory = WTFMove(selector); }
    void clearTagHistory() { m_tagHistory.reset(); }
    void insertTagHistory(CSSSelector::RelationType before, std::unique_ptr<CSSParserSelector>, CSSSelector::RelationType after);
    void appendTagHistory(CSSSelector::RelationType, std::unique_ptr<CSSParserSelector>);
    void appendTagHistory(CSSParserSelectorCombinator, std::unique_ptr<CSSParserSelector>);
    void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false);
    std::unique_ptr<CSSParserSelector> releaseTagHistory();

private:
    std::unique_ptr<CSSSelector> m_selector;
    std::unique_ptr<CSSParserSelector> m_tagHistory;
};

inline bool CSSParserSelector::hasShadowDescendant() const
{
    return m_selector->relation() == CSSSelector::ShadowDescendant;
}

inline bool CSSParserSelector::needsImplicitShadowCombinatorForMatching() const
{
    return match() == CSSSelector::PseudoElement
        && (pseudoElementType() == CSSSelector::PseudoElementWebKitCustom
#if ENABLE(VIDEO_TRACK)
            || pseudoElementType() == CSSSelector::PseudoElementCue
#endif
            || pseudoElementType() == CSSSelector::PseudoElementPart
            || pseudoElementType() == CSSSelector::PseudoElementWebKitCustomLegacyPrefixed);
}

inline bool CSSParserSelector::isPseudoElementCueFunction() const
{
#if ENABLE(VIDEO_TRACK)
    return m_selector->match() == CSSSelector::PseudoElement && m_selector->pseudoElementType() == CSSSelector::PseudoElementCue;
#else
    return false;
#endif
}

}
