#!/usr/bin/python3
import argparse
import json
import os
import select
import socket
import sys

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Register a file for transmission via iep-storward')
    parser.add_argument('--local', type=str,
        required=True,
        help='The path of the file to be registered',
    )
    parser.add_argument('--remote', type=str,
        required=True,
        help='The name under which to store the file remotely',
    )
    parser.add_argument('--topic', type=str,
        required=True,
        help='The topic on which to announce the file',
    )
    parser.add_argument('--host', type=str,
        default='localhost',
        help="The iep-storward host",
    )
    parser.add_argument('--port', type=int,
        default=46000,
        help="The iep-storward TCP port",
    )
    parser.add_argument('--timeout', type=float,
        default=5.0,
        help='The number of seconds to wait before giving up',
    )
    args = parser.parse_args()
    
    if not os.path.isfile(args.local) or not os.access(args.local, os.R_OK):
        print("Unable to read file at {path}".format(
            path=args.local,
        ))
        sys.exit(1)
        
    try:
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client.connect((args.host, args.port))
    except Exception as e:
        print("Unable to connect to iep-storward: {error}".format(
            error=e,
        ))
        sys.exit(3)
    else:
        try:
            payload = json.dumps({
                'local': args.local,
                'remote': args.remote,
            })
            message = '\n'.join((
                args.topic,
                str(len(payload)),
                payload
            ))
            client.send(message.encode('utf-8'))
            client.shutdown(socket.SHUT_WR)
            
            while True: #EINTR can interrupt select()
                try:
                    (r_ready, w_ready, e_ready) = select.select([client], [], [], args.timeout)
                    if not r_ready:
                        print("No response received from iep-storward")
                        sys.exit(4)
                    break
                except Exception as e:
                    print("select() did not succeed; repeating")
                    
            #Technically, this should be repeated until all data has been received,
            #but all that should come back is a seven-byte string, and that will
            #fit in every frame that can support TCP
            response = client.recv(256)
            if not response.startswith(b'RES:OK:'):
                print("Failure received from iep-storward: {response}".format(
                    response=response,
                ))
                sys.exit(5)
        finally:
            try:
                client.close()
            except Exception as e:
                print("Unable to close socket: {error}".format(
                    error=e,
                ))
                
