# -*- coding: utf8 -*-

"""
Copyright (C) 2007 Adolfo González Blázquez <code@infinicode.org>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU 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 General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

If you find any bugs or have any suggestions email: code@infinicode.org
"""

import sys
import socket
from codes import Codes
from message import *
from fileformat import *

class Protocol:

        def __init__(self, debug=True):
                # DATA
                self._HOST = 'localhost'
                self._PORT = 4001
                self._LOGIN = 'admin'
                self._PASSWORD = ''

                self.debug = debug


        def set_connection_data(self, host, port, login, password):
                self._HOST = host
                self._PORT = int(port)
                self._LOGIN = login
                self._PASSWORD = password

        # Open the connection with the server and returns objects for
        # sending and recieving data to/from the server
        def open_connection(self):
                try:
                        if self.debug: print "[C] Trying to connect to %s..." % (self._HOST)
                        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                        self.socket.settimeout(5)
                        self.socket.connect((self._HOST, self._PORT))
                except Exception, e:
                    if self.debug: print "      ERROR: Can not connect!"
                    if self.debug: print "      Exception:", e
                    return ''
                return self.socket


        def close_connection(self):
                self.socket.close()
                self.socket = None
                if self.debug: print "[S] Connection closed"


        # Login to the server
        def client_protocolversion(self):
                # GUi sends its protocol version
                if self.debug: print "[C00] GuiProtocolVersion"
                m = MessageSender(self.socket, Codes.client['GuiProtocolVersion'])
                m.int32(41)
                m.send()


        # Poll mode
        def client_pollmode(self, enabled):
                if self.debug: print "[C47] GuiExtensions (Poll Mode)"
                m = MessageSender(self.socket, Codes.client['GuiExtensions'])
                m.int16(1)
                m.int32(1)
                m.int8(enabled)
                m.send()


        # GUI sends Password message
        def client_password(self):
                code = str(Codes.client['Password'])
                if self.debug: print '[C'+code+'] Password'
                m = MessageSender(self.socket, Codes.client['Password'])
                m.string(self._PASSWORD)
                m.string(self._LOGIN)
                m.send()

        def server_badpassword(self):
                code = str(Codes.server['BadPassword'])
                if self.debug: print '[S'+code+'] BadPassword'


        # Get server's CoreProtocol
        def server_coreprotocol(self, m):
                if self.debug: print "[S00] CoreProtocol"
                prot = m.int32()                                # Protocol
                gmax = m.int32()                                # Max Opcode GUI
                cmax = m.int32()                                # Max Opcode Core
                if self.debug: print "  Protocol", prot, '(', gmax, '/', cmax, ')'


        # Get server's NetworkInfo
        def server_networkinfo(self, m):
                if self.debug: print "[S20] NetworkInfo"
                id = m.int32()                          # Network id
                name = m.string()                       # Network name
                enabled = m.int8()                      # Enabled
                config = m.string()                     # Name of network config file
                up = m.int64()                          # Number of bytes uploaded on network
                down = m.int64()                        # Number of bytes downloaded on network
                servers = m.int32()                     # Number of connected servers (only protocol 18 ?)
                flags = m.list('int16')         # Network flags (only protocol 18 ?)
                if self.debug: print "  ", enabled, name, up, down


        # Get server's ConsoleMessage
        def server_consolemessage(self, m):
                if self.debug: print "[S19] ConsoleMesssage"
                if self.debug: print "  ", m.string()


        # Get server's ClientStats
        def server_clientstats(self, m):
                code = str(Codes.server['ClientStats'])
                if self.debug: print '[S'+code+'] ClientStats'
                total_uploaded = m.int64()
                total_downloaded = m.int64()
                total_shared = m.int64()
                shared = m.int32()
                tcp_uprate = m.int32()
                tcp_downrate = m.int32()
                udp_uprate = m.int32()
                udp_downrate = m.int32()
                downloading = m.int32()
                finished = m.int32()
                if self.debug: print "  ", round(tcp_uprate/1024.00,2), round(tcp_downrate/1024.00, 2)
                return [round(tcp_uprate/1024.00, 2), \
                                round(tcp_downrate/1024.00, 2), \
                                downloading, \
                                0, \
                                shared, \
                                total_shared, \
                                total_uploaded]

        def client_getdownloadingfiles(self):
                code = str(Codes.client['GetDownloadingFiles'])
                if self.debug: print '[C'+code+'] GetDownloadingFiles'
                m = MessageSender(self.socket, Codes.client['GetDownloadingFiles'])
                m.send()

        def server_optionsinfo(self, m):
                code = str(Codes.server['OptionsInfo'])
                if self.debug: print '[S'+code+'] OptionsInfo'

                print repr(m.data)
                """
                l = m.list(['string', 'string'])
                for i in l:
                        print l
                """

        def server_downloadingfiles(self, m):
                code = str(Codes.server['DownloadingFiles'])
                if self.debug: print '[S'+code+'] DownloadingFiles'
                active = 0
                size = m.int16()
                for i in range(size):
                        fileid = m.int32()
                        print " File", fileid
                        netid = m.int32()
                        filenames = m.list('string')
                        md4 = m.chararray(16)
                        filesize = m.int64()
                        downloaded = m.int64()
                        sources = m.int32()
                        clients = m.int32()
                        state = m.int8()
                        if state == 6: reason = m.string()
                        if state == 0: active +=1
                        chunks = m.string()
                        availability = m.list(['int32', 'string'])
                        speed = m.float()
                        chunkages = m.list('int32')
                        fileage = m.int32()
                        fileformat = FileFormat(m)
                        print fileformat.get_data()
                        filename = m.string()
                        lastseen = m.int32()
                        priority = m.uint32()
                        comment = m.string()
                        links = m.list('string')
                        subfiles = m.list(['string', 'int64', 'string'])
                        format = m.string()
                        comments = m.list(['int32', 'int8', 'string', 'int8', 'string'])
                        user = m.string()
                        group = m.string()
                return active