/*
 * Copyright 2006 The Apache Software Foundation or its licensors, as
 * applicable.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef _ACTIVEMQ_CORE_ACTIVEMQCONSTANTS_H_
#define _ACTIVEMQ_CORE_ACTIVEMQCONSTANTS_H_

#include <string>
#include <map>
#include <activemq/util/Config.h>

namespace activemq {
namespace core {

    /**
     * Class holding constant values for various ActiveMQ specific things
     * Each constant is defined as an enumeration and has functions that
     * convert back an forth between string and enum values.
     */
    class AMQCPP_API ActiveMQConstants {
    public:

        // Flags to indicate Transaction States.
        enum TransactionState {
            TRANSACTION_STATE_BEGIN = 0,
            TRANSACTION_STATE_PREPARE = 1,
            TRANSACTION_STATE_COMMITONEPHASE = 2,
            TRANSACTION_STATE_COMMITTWOPHASE = 3,
            TRANSACTION_STATE_ROLLBACK = 4,
            TRANSACTION_STATE_RECOVER = 5,
            TRANSACTION_STATE_FORGET = 6,
            TRANSACTION_STATE_END = 7
        };

        // Flags to be applied when sending the Destination Info Command.
        enum DestinationActions {
            DESTINATION_ADD_OPERATION = 0,
            DESTINATION_REMOVE_OPERATION = 1
        };

        // Represents the Acknowledgment types that are supported for the
        // Message Ack Command.
        enum AckType {
            ACK_TYPE_DELIVERED   = 0,  // Message delivered but not consumed
            ACK_TYPE_POISON      = 1,  // Message could not be processed due to
                                       // poison pill but discard anyway
            ACK_TYPE_CONSUMED    = 2,  // Message consumed, discard
            ACK_TYPE_REDELIVERED = 3,  // Message has been re-delivered.
            ACK_TYPE_INDIVIDUAL  = 4,  // Acks a single message at a time.
            ACK_TYPE_UNMATCHED   = 5,  // Durable sub doesn't match selector
            ACK_TYPE_EXPIRED     = 6   // Message expired.
        };

        /**
         * These values represent the options that can be appended to an
         * Destination name, i.e. /topic/foo?consumer.exclusive=true
         */
        enum DestinationOption {
            CONSUMER_PREFECTCHSIZE,
            CUNSUMER_MAXPENDINGMSGLIMIT,
            CONSUMER_NOLOCAL,
            CONSUMER_DISPATCHASYNC,
            CONSUMER_RETROACTIVE,
            CONSUMER_SELECTOR,
            CONSUMER_EXCLUSIVE,
            CONSUMER_PRIORITY,
            NUM_OPTIONS
        };

        /**
         * These values represent the parameters that can be added to the
         * connection URI that affect the ActiveMQ Core API
         */
        enum URIParam {
            CONNECTION_SENDTIMEOUT,
            CONNECTION_PRODUCERWINDOWSIZE,
            CONNECTION_CLOSETIMEOUT,
            CONNECTION_ALWAYSSYNCSEND,
            CONNECTION_USEASYNCSEND,
            CONNECTION_USECOMPRESSION,
            CONNECTION_DISPATCHASYNC,
            PARAM_USERNAME,
            PARAM_PASSWORD,
            PARAM_CLIENTID,
            CONNECTION_CONNECTRESPONSETIMEOUT,
            NUM_PARAMS
        };

        static const std::string& toString(const DestinationOption option) {
            return StaticInitializer::destOptions[option];
        }

        static DestinationOption toDestinationOption(const std::string& option) {
            std::map<std::string, DestinationOption>::iterator iter = StaticInitializer::destOptionMap.find(option);

            if (iter == StaticInitializer::destOptionMap.end()) {
                return NUM_OPTIONS;
            }

            return iter->second;
        }

        static const std::string& toString(const URIParam option) {
            return StaticInitializer::uriParams[option];
        }

        static URIParam toURIOption(const std::string& option) {
            std::map<std::string, URIParam>::iterator iter = StaticInitializer::uriParamsMap.find(option);

            if (iter == StaticInitializer::uriParamsMap.end()) {
                return NUM_PARAMS;
            }

            return iter->second;
        }

        class StaticInitializer {
        public:
            StaticInitializer();
            virtual ~StaticInitializer() {}

            static std::string destOptions[NUM_OPTIONS];
            static std::string uriParams[NUM_PARAMS];
            static std::map<std::string, DestinationOption> destOptionMap;
            static std::map<std::string, URIParam> uriParamsMap;
        };

    private:

        static StaticInitializer staticInits;

    };

}}

#endif /*_ACTIVEMQ_CORE_ACTIVEMQCONSTANTS_H_*/
