/**
 * GMyth Library
 *
 * @file gmyth/gmyth_socket.h
 * 
 * @brief <p> MythTV socket implementation, according to the MythTV Project
 * (www.mythtv.org). 
 * 
 * This component provides basic socket functionalities to interact with
 * the Mythtv backend.
 * <p>
 *
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br> 
 *
 * 
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * 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 Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __GMYTH_SOCKET_H__
#define __GMYTH_SOCKET_H__

#include <glib-object.h>

#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
#include <glib.h>

#include "gmyth_stringlist.h"

G_BEGIN_DECLS
#define GMYTH_SOCKET_TYPE               (gmyth_socket_get_type ())
#define GMYTH_SOCKET(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE, GMythSocket))
#define GMYTH_SOCKET_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE, GMythSocketClass))
#define IS_GMYTH_SOCKET(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SOCKET_TYPE))
#define IS_GMYTH_SOCKET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE))
#define GMYTH_SOCKET_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SOCKET_TYPE, GMythSocketClass))
typedef struct _GMythSocket GMythSocket;
typedef struct _GMythSocketClass GMythSocketClass;

struct _GMythSocketClass {
    GObjectClass    parent_class;

    /*
     * callbacks 
     */
    /*
     * no one for now 
     */
};

struct _GMythSocket {
    GObject         parent;

    GMutex         *mutex;

    /*
     * socket descriptor 
     */
    gint            sd;
    GIOChannel     *sd_io_ch;

    gchar          *hostname;
    gint            port;
    gint            mythtv_version;
};

/*
 * used when no protocol version number was negotiated 
 */
#define	MYTHTV_CANNOT_NEGOTIATE_VERSION		0

GType           gmyth_socket_get_type(void);

GMythSocket    *gmyth_socket_new();

GIOChannel     *gmyth_socket_get_io_channel(GMythSocket * gmyth_socket);

gboolean        gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket);
gboolean        gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket);

gboolean        gmyth_socket_send_command(GMythSocket * gmyth_socket,
                                          GString * command);
GString        *gmyth_socket_receive_response(GMythSocket * gmyth_socket);
gint            gmyth_socket_sendreceive_stringlist(GMythSocket *
                                                    gmyth_socket,
                                                    GMythStringList *
                                                    str_list);

gboolean        gmyth_socket_connect(GMythSocket * gmyth_socket,
                                     const gchar * hostname, gint port);
gboolean        gmyth_socket_connect_with_timeout(GMythSocket *
                                                  gmyth_socket,
                                                  const gchar * hostname,
                                                  gint port,
                                                  guint timeout);

gboolean        gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket,
                                                const gchar *
                                                hostname_backend,
                                                gint port,
                                                gboolean blocking_client);

gboolean        gmyth_socket_connect_to_backend_events(GMythSocket *
                                                       gmyth_socket,
                                                       const gchar *
                                                       hostname_backend,
                                                       gint port,
                                                       gboolean
                                                       blocking_client);

gchar          *gmyth_socket_get_primary_addr(void);

GString        *gmyth_socket_get_local_hostname(void);

void            gmyth_socket_close_connection(GMythSocket * gmyth_socket);

gboolean        gmyth_socket_check_protocol_version(GMythSocket *
                                                    gmyth_socket);
gint            gmyth_socket_check_protocol_version_number(GMythSocket *
                                                           gmyth_socket,
                                                           gint
                                                           mythtv_version);

gint            gmyth_socket_get_protocol_version(GMythSocket *
                                                  gmyth_socket);

gboolean        gmyth_socket_write_stringlist(GMythSocket * gmyth_socket,
                                              GMythStringList * str_list);
gint            gmyth_socket_read_stringlist(GMythSocket * gmyth_socket,
                                             GMythStringList * str_list);
G_END_DECLS
#endif                          /* __GMYTH_SOCKET_H__ */
