#!/usr/bin/env python

import os,sys
import glob

# assuming phcomm is in ../libs relative to this file, now import finds it
# even if that directory is not in environment variable PYTHONPATH
sys.path.append( os.path.join( os.path.split(__file__)[0], '../libs' ) )
import phcomm

class sync_server( phcomm.Server ):

    def __init__( self, config_file, verbose=0 ):
        # read in the config file
        # it should create variables COM_PORT and SYNC_FILES
        d = {}
        execfile( config_file, {}, d )
        # chdir to the directory of the config_file (if not already there)
        # so relative paths work
        try:
            os.chdir( os.path.split( config_file )[0] )
        except:
            pass
        self.sync_files = d['SYNC_FROM_PC']
        self.download_files = d['SYNC_TO_PC']
        # connect to phone
        sock = phcomm.connect_PC2phone( com_port=d['COM_PORT'], verbose=verbose )
        # initialize parent class
        phcomm.Server.__init__( self, sock, verbose )

    def cmd_msg( self, line ):
        print line.split( ' ', 1)[1]

    def cmd_sync( self, line ):
        # create lists of local and corresponding remote files and checksums
        remotefiles, localfiles, checksums = [], [], []
        for dest, srcs in self.sync_files:
            # for each destination directory there can be several
            # source directories
            dpath = os.path.normpath( dest )
            if not isinstance(srcs, tuple) and not isinstance(srcs, list):
                # force sources to list
                srcs = [ srcs ]
            for src in srcs:
                # for each source location
                for f in glob.glob( src ):
                    # find matching files
                    file = os.path.split(f)[1]
                    # create remote name, local name, checksum
                    remotefiles.append( os.path.join( dpath, file ) )
                    localfiles.append( os.path.normpath( f ) )
                    checksums.append( phcomm.file_checksum( f ) )
        # send to phone a list of remote, local, checksum triplets
        self.send_data( repr(zip(remotefiles, localfiles, checksums)) )

        # then send the info about the files that you want to download to pc
        self.send_data( repr( self.download_files ) )
        
        print

    def cmd_getfile( self, line ):
        """the phone asks to get a file"""
        filename = self.recv_data()
        self.send_data( open( filename, 'rb' ).read() )
        print 'sent file:', filename

    def cmd_sendfile( self, line ):
        """the phone sends a file"""
        filename = self.recv_data()
        print filename
        open( filename, 'wb' ).write( self.recv_data() )
        print 'received file:', filename

    def cmd_offerfile( self, line ):
        """the phone offers a filename and checksum, if that file with
        matching checksum exists, don't bother with it, otherwise get it"""
        filename = self.recv_data()
        crc = int( line.split()[1] )
        pc_crc = phcomm.file_checksum( filename )
        #print filename, crc, pc_crc
        if crc == pc_crc:
            # don't need this file
            self.send( '0' )
            #print 'skipping existing file', filename
        else:
            self.send( '1' )
            open( filename, 'wb' ).write( self.recv_data() )
            print 'received file:', filename

if __name__ == '__main__':

    if len(sys.argv) < 2:
        print "usage: syncd.py <configfile>"
        print """

    convenience tool to bypass the upload-install-run cycle.
    configfile specifies which files you want uploaded to the phone.
    Run the sync.py on the phone, connect to the PC running syncd, and
    the phone will automatically download the files.
"""
    #sync_server( sys.argv[1], verbose=True ).run()
    print 'starting sync demon'
    sync_server( sys.argv[1] ).run()
