from msg import *
from network import Network
from random import random
import sys

class VirtualServer:
    """This is the parent class to all types of ReliableServers.  It's
    a bit of hack, but doing it this way allows us to run multiple
    servers sharing the same file state (i.e., for multihoming).

    B{Do not} alter this class for the problem set.
    """

    def sendData( self, host, port, msg ):
        self.mhrs.sendData( host, port, msg )

    def handleFinAck( self, host, port, msg ):

        # must override to let the mhrs reset all the vserver fields

        if(self.state == self.STATE_SENT_FIN):
            # done! delete connection state
            print "File download successful. Connection to client closed."
            self.network.cancelTimeout( host, port, msg.seqno )
            self.mhrs.resetFields()

    def openFile( self, host, port, filename ):
        try:
            self.mhrs.fd = open( filename, "r" )
            return True
        except:
            print "Error: File doesn't exist. Sending retry to client"
            return False

    def closeFile( self, host, port ):
        self.mhrs.fd.close()

    def nextDataChunk( self, host, port ):
        return self.mhrs.fd.read( self.chunk_size )

    def setSeqNo( self, host, port ):
        # Pick a random sequence number
        self.mhrs.seqno = int( random() * 16384 )

    def nextSeqNo( self, host, port ):
        currnum = self.mhrs.seqno
        self.mhrs.seqno = self.mhrs.seqno+1
        return currnum
    
    def getCurrSeqNo(self, host, port ):
        return self.mhrs.seqno

    def canSendFin( self, host, port ):
        return self.mhrs.canSendFin( host, port )


def virtualizeServer( server, mhrs ):
    """Takes in a server, and virtualizes all of its relevant methods,
    so that those methods will share data via a multi-homed server instead.
    """

    server.mhrs = mhrs
    server.sendData = lambda h,p,s:VirtualServer.sendData(server,h,p,s)
    server.handleFinAck = lambda h,p,m: VirtualServer.handleFinAck(server,h,
                                                                   p,m)
    server.openFile = lambda h,p,f: VirtualServer.openFile(server,h,p,f)
    server.closeFile = lambda h,p: VirtualServer.closeFile(server,h,p)
    server.nextDataChunk = lambda h,p: VirtualServer.nextDataChunk(server,h,p)
    server.setSeqNo = lambda h,p: VirtualServer.setSeqNo(server,h,p)
    server.nextSeqNo = lambda h,p: VirtualServer.nextSeqNo(server,h,p)
    server.getCurrSeqNo = lambda h,p: VirtualServer.getCurrSeqNo(server,h,p)
    server.canSendFin = lambda h,p: VirtualServer.canSendFin(server,h,p)
