/*
 * Copyright (C) 2009 - 2010 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */
/* $Id$ */

#pragma once

#include <commontypes.h>
#include <vector>
#include <IRunner.h>

namespace Funambol
{
    class TransportAgent;
}

namespace NS_DM_Client
{
    class ProfileComponentsHolder;

    namespace NS_Communication
    {

        class WIBConnector : public NS_Common::IRunner
        {
        public:
            typedef std::vector<unsigned char> dns_answer_t;

            enum EnumDNSServiceProtocol
            {
                e_Unknown = 0,
                e_UDP,
                e_TCP
            };

			WIBConnector(ProfileComponentsHolder& pch, bool plainBootstrap, bool cipherHeaderPresent, 
				const String& wibServiceDiscoveryTarget, const String& wibDnsServer,
				int retries/* = 0*/, int retryInterval/* = 1*/);
            virtual ~WIBConnector();

            /// perform WIB with retries number in seconds interval (retry_interval)
            bool FetchBootstrapData(buffer_t& bsdata, const buffer_t& msid, int retries = 0, int retryInterval = 1,
                const char* domain = 0, const char* service = 0);

        protected:
            struct ServerInfo
            {
                String  server;
                int     port;
                int     priority;
                int     weight;

				ServerInfo()
					:port(0), priority(0), weight(0)
				{}
            };

            enum EnumWIBQueryResponseCode
            {
                e_WIBQ_Undefined = 0,
                e_WIBQ_OK = 200,
                e_WIBQ_Redirect = 302,
                e_WIBQ_BadRequest = 400,
                e_WIBQ_Forbidden = 403,
                e_WIBQ_NotFound = 404
            };

            typedef std::list<ServerInfo>   ServerList;
            /// fetch WIB servers list from DNS
            bool    getWIBServers(ServerList& servers);

            /// build DNS SRV query
            bool    buildSRVquery(const char* domainname, String& query);

            /// build WIB server request parameters
            bool    buildWIBrequest(const String& msid, String& request);

            /// parse DNS SRV response
            bool parseSRVresponse(const dns_answer_t& answ, ServerList& servers);

            /// query URI using HTTP GET method
            bool    query(const String& uri, EnumWIBQueryResponseCode& resp_code, buffer_t& response, String& resp_type);

            /// format URI for WIB query
            bool    formatQueryURI(String& uri, const ServerInfo& i, const String& request) const;

            /// validate and decrypt bootstrap message
            bool    checkBootstrapMessage(const char* buf, size_t size, buffer_t& bsdata) const;

            /// Sleep for 'internal' seconds
            static bool S_sleep(int interval);

            bool getMSID(buffer_t& msid);
            bool parseMACAddress(buffer_t& msid, const String& macAddress);

            // from IRunner
            virtual void    Start();
            virtual void    Stop();

        private:
            WIBConnector(const WIBConnector&);
            WIBConnector& operator = (const WIBConnector&);

        private:
            String m_domain;
            String m_service;
            volatile int m_retries;
            int m_retryInterval;

            ProfileComponentsHolder& m_pch;

			Funambol::TransportAgent*	m_pTransportAgent;

			bool m_plainBootstrap;
			bool m_cipherHeaderPresent;

			String m_wibDiscoveryTarget;
			String m_wibDnsServer;

        };
    }
}
