/*
 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#if ENABLE(CONTENT_EXTENSIONS)

#include "ContentExtensionsDebugging.h"
#include <wtf/HashMap.h>
#include <wtf/Vector.h>

namespace WebCore {

namespace ContentExtensions {

struct DFA;

struct CharRange {
    char first;
    char last;
    unsigned size() const { return last - first + 1; }
};

// A DFANode abstract the transition table out of a DFA state. If a state is accepting, the DFANode also have
// the actions for that state.
class DFANode {
public:
    struct ConstRangeIterator {
        const DFA& dfa;
        uint32_t position;

        const ConstRangeIterator& operator*() const { return *this; }

        bool operator==(const ConstRangeIterator& other) const
        {
            ASSERT(&dfa  == &other.dfa);
            return position == other.position;
        }
        bool operator!=(const ConstRangeIterator& other) const { return !(*this == other); }

        ConstRangeIterator& operator++()
        {
            ++position;
            return *this;
        }

        const CharRange& range() const;
        uint32_t target() const;

        char first() const { return range().first; }
        char last() const { return range().last; }
        uint32_t data() const { return target(); }
    };

    struct IterableConstRange {
        const DFA& dfa;
        uint32_t rangesStart;
        uint32_t rangesEnd;

        ConstRangeIterator begin() const { return { dfa, rangesStart }; }
        ConstRangeIterator end() const { return { dfa, rangesEnd }; }
    };

    IterableConstRange transitions(const DFA& dfa) const
    {
        return IterableConstRange { dfa, m_transitionsStart, m_transitionsStart + m_transitionsLength };
    }

    struct RangeIterator {
        DFA& dfa;
        uint32_t position;

        RangeIterator& operator*() { return *this; }

        bool operator==(const RangeIterator& other) const
        {
            ASSERT(&dfa  == &other.dfa);
            return position == other.position;
        }
        bool operator!=(const RangeIterator& other) const { return !(*this == other); }

        RangeIterator& operator++()
        {
            ++position;
            return *this;
        }

        const CharRange& range() const;
        uint32_t target() const;
        void resetTarget(uint32_t);

        char first() const { return range().first; }
        char last() const { return range().last; }
        uint32_t data() const { return target(); }
    };

    struct IterableRange {
        DFA& dfa;
        uint32_t rangesStart;
        uint32_t rangesEnd;

        RangeIterator begin() const { return { dfa, rangesStart }; }
        RangeIterator end() const { return { dfa, rangesEnd }; }
    };

    IterableRange transitions(DFA& dfa)
    {
        return IterableRange { dfa, m_transitionsStart, m_transitionsStart + m_transitionsLength };
    }

    // FIXME: Stop minimizing killed nodes and add ASSERT(!isKilled()) in many functions here.
    void kill(DFA&);
    Vector<uint64_t> actions(const DFA&) const;
    bool containsTransition(char, const DFA&) const;
    
    bool isKilled() const { return m_flags & IsKilled; }
    bool hasActions() const { return !!m_actionsLength; }
    uint16_t actionsLength() const { return m_actionsLength; }
    uint32_t actionsStart() const { return m_actionsStart; }

    bool canUseFallbackTransition(const DFA&) const;
    uint32_t bestFallbackTarget(const DFA&) const;

    void setActions(uint32_t start, uint16_t length)
    {
        ASSERT(!m_actionsStart);
        ASSERT(!m_actionsLength);
        m_actionsStart = start;
        m_actionsLength = length;
    }
    void setTransitions(uint32_t start, uint16_t length)
    {
        ASSERT(!m_transitionsStart);
        ASSERT(!m_transitionsLength);
        m_transitionsStart = start;
        m_transitionsLength = length;
    }

private:
    uint32_t m_actionsStart { 0 };
    uint32_t m_transitionsStart { 0 };
    uint16_t m_actionsLength { 0 };
    uint8_t m_transitionsLength { 0 };
    
    uint8_t m_flags { 0 };
    const uint8_t IsKilled = 0x01;
};

COMPILE_ASSERT(sizeof(DFANode) <= 16, Keep the DFANodes small);

} // namespace ContentExtensions
} // namespace WebCore

#endif // ENABLE(CONTENT_EXTENSIONS)
