/*****************************************************************************
 *
 * $Id$
 *
 * Copyright (C) 2009 - 2012  Richard Hacker <lerich@gmx.net>
 *                            Florian Pose <fp@igh-essen.com>
 *
 * This file is part of the PdCom library.
 *
 * The PdCom library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * The PdCom 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 Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the PdCom Library. If not, see <http://www.gnu.org/licenses/>.
 *
 ****************************************************************************/

#ifndef MSRPROTOCOLHANDLER_H
#define MSRPROTOCOLHANDLER_H

#include "../ProtocolHandler.h"
#include "pdcom/Exception.h"

#include <expat_external.h>
#include <expat.h>
#include <string>
#include <set>
#include <vector>
#include <cstring>

namespace MSRProto {

class Param;
class Channel;
class Variable;

/****************************************************************************/

/** MSR-specific protocol handler.
 */

class ProtocolHandler: public PdCom::ProtocolHandler {
    public:
        ProtocolHandler(PdCom::Process *process, std::ostream *os);
        ~ProtocolHandler();

        /** Test whether MSR can parse the buffer
         *
         * \return Reference to new ProtocolHandler if successful
         */
        static PdCom::ProtocolHandler* tryParse(const char *buf, size_t len,
                PdCom::Process *process, std::ostream *os);

        size_t parse(const char *buf, size_t len);
        bool connected() const { return state == Ready; }

        bool hasFeature(const std::string &feature) const;

        std::map<std::string,std::string> getInfo() const;

        void sendBroadcast(const std::string &,
                const std::string & = "text");

    private:
        /* Properties of the server */
        std::string name;
        std::string host;
        std::string app;
        std::string appVersion;
        unsigned int version;
        std::set<std::string> feature;
        unsigned int recievebufsize;

        std::vector<Param*> parameter;
        std::vector<Channel*> channel;
        unsigned int maxParamIdx;
        unsigned int maxChannelIdx;
        std::string featureStr;

        unsigned int admin;
        unsigned int write;

        enum ConnectionState {
            NotConnected, Connected,
            ReadParam, ReadParamList,
            ReadChan, ReadChanList,
            Ready
        };
        ConnectionState state;

        enum ConnectedState {
            Idle, ReadData,
        };
        ConnectedState connected_state;
        std::string dataTime;  // time tag of <data time="...">

        XML_Parser xmlParser;
        int xmlDepth;
        static void XMLCALL ExpatInitStartTag(void *,
                const char *, const char **);
        static void XMLCALL ExpatInitEndTag(void *, const char *);
        static void XMLCALL ExpatConnectedStartTag(void *,
                const char *, const char **);
        static void XMLCALL ExpatConnectedEndTag(void *, const char *);
        void initStartTag(const char *, const char **);
        void initEndTag(const char *);
        void connectedStartTag(const char *, const char **);
        void connectedEndTag(const char *);
        void processInfoTag(const char**);
        void processBroadcastTag(const char**);

        void login() const;
        void sendChannelList() const;
        void sendParameterList() const;

        static std::string xmlEscape(const std::string &);
};

} // namespace PdCom

#endif // MSRPROTOCOLHANDLER_H

/****************************************************************************/
