/*
 * Copyright 2009 Funambol, Inc.
 *
 * 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.
 */

/* $Id$ */

#pragma once

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

#ifdef PLATFORM_ANDROID
#include "../../src/android/resolv_declarations.h" // add declarations for resolv infrastructure
#endif

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, 
				const String& wibServer, int wibServerPort, const String& wibRequestURI, 
				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;
			
			String	m_wibServer;
			int		m_wibServerPort;
			String	m_wibRequestURI;

        };
    }
}
