/*
 * Copyright 2005 Frerich Raabe <raabe@kde.org>
 * Copyright (C) 2006, 2013 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 THE AUTHOR ``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 THE AUTHOR 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

#include "XPathNodeSet.h"

namespace WebCore {
    namespace XPath {
    
        class Value {
        public:
            enum Type { NodeSetValue, BooleanValue, NumberValue, StringValue };
            
            Value(bool value) : m_type(BooleanValue), m_bool(value) { }
            Value(unsigned value) : m_type(NumberValue), m_number(value) { }
            Value(double value) : m_type(NumberValue), m_number(value) { }

            Value(const String& value) : m_type(StringValue), m_data(Data::create(value)) { }
            Value(const char* value) : m_type(StringValue), m_data(Data::create(value)) { }

            explicit Value(NodeSet&& value)
                : m_type(NodeSetValue), m_data(Data::create(WTFMove(value)))
            { }
            explicit Value(Node* value)
                : m_type(NodeSetValue), m_data(Data::create(value))
            { }
            explicit Value(RefPtr<Node>&& value)
                : m_type(NodeSetValue), m_data(Data::create(WTFMove(value)))
            { }

            Type type() const { return m_type; }

            bool isNodeSet() const { return m_type == NodeSetValue; }
            bool isBoolean() const { return m_type == BooleanValue; }
            bool isNumber() const { return m_type == NumberValue; }
            bool isString() const { return m_type == StringValue; }

            const NodeSet& toNodeSet() const;
            bool toBoolean() const;
            double toNumber() const;
            String toString() const;

            // Note that the NodeSet is shared with other Values that this one was copied from or that are copies of this one.
            NodeSet& modifiableNodeSet();

        private:
            // This constructor creates ambiguity so that we don't accidentally call the boolean overload for pointer types.
            Value(void*) = delete;

            struct Data : public RefCounted<Data> {
                static Ref<Data> create() { return adoptRef(*new Data); }
                static Ref<Data> create(const String& string) { return adoptRef(*new Data(string)); }
                static Ref<Data> create(NodeSet&& nodeSet) { return adoptRef(*new Data(WTFMove(nodeSet))); }
                static Ref<Data> create(RefPtr<Node>&& node) { return adoptRef(*new Data(WTFMove(node))); }

                String string;
                NodeSet nodeSet;

            private:
                Data() { }
                explicit Data(const String& string)
                    : string(string)
                { }
                explicit Data(NodeSet&& nodeSet)
                    : nodeSet(WTFMove(nodeSet))
                { }
                explicit Data(RefPtr<Node>&& node)
                    : nodeSet(WTFMove(node))
                { }
            };

            Type m_type;
            bool m_bool;
            double m_number;
            RefPtr<Data> m_data;
        };

    } // namespace XPath
} // namespace WebCore
