import selectors
import socket,os,sys
BASE_DIR= os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

sel = selectors.DefaultSelector()

cmdlist=['put','get']

class Ftp(object):
    def __init__(self):
        pass

    def accept(self,sock, mask):
        conn, addr = sock.accept()  # Should be ready
        conn.setblocking(False)
        sel.register(conn, selectors.EVENT_READ, self.read)

    def read(self,conn, mask):
        # while True:
            cmd = conn.recv(1024).decode().split()  # Should be ready
            if len(cmd) != 2 :
                conn.send(b'wrong command!')
            elif cmd[0] in cmdlist:
                # conn.send(b'ok')
                if hasattr(self,'cmd_%s'%cmd[0]):
                    fc = getattr(self, "cmd_%s" % cmd[0])
                    fc(conn,cmd[-1])
            else:
                print('closing', conn)
                sel.unregister(conn)
                conn.close()

    def cmd_put(self,conn,file):
        conn.setblocking(True)
        print("Put [%s] to client" % file)
        conn.send(b"put01")  ## please send the file size
        filesize = int(conn.recv(1024).decode())
        conn.send(b"put02")  ## please send the file
        upload_file=os.path.join(BASE_DIR,'data',os.path.basename(file))

        with open(upload_file, 'wb') as f:
            size = 0
            while True:
                if (filesize - size) > 10240:
                    recvsize = 10240
                else:
                    recvsize = filesize - size
                data = conn.recv(recvsize)
                size += len(data)
                if int(filesize) == size:
                    f.write(data)
                    f.flush()
                    print("Upload [%s] done ....." % upload_file)
                    conn.send(b'putok')
                    break
                f.write(data)
                f.flush()

    def cmd_get(self,conn,file):
        conn.setblocking(True)
        if os.path.exists(file):
            file_size = str(os.path.getsize(file)).encode()
            conn.send(b'get01')  ## ready to send file size
            rectag1 = conn.recv(1024).decode()
            if rectag1 == 'get01':conn.send(file_size)
            rectag2 = conn.recv(10240).decode()
            if rectag2 == 'get02':
                while True:
                    with open(file, 'rb') as f:
                        d = f.read()
                        conn.sendall(d)
                    rectag = conn.recv(1024).decode()
                    if rectag == 'getok':
                        print("Download [%s] done!" % file)
                        break
        else:
            print("The [%s] not exists!" %file)
            conn.send(b'get00')

def run():
    start_ftp = Ftp()
    sock = socket.socket()
    sock.bind(('localhost', 9000))
    sock.listen(100)
    sock.setblocking(False)
    sel.register(sock, selectors.EVENT_READ, start_ftp.accept)


    while True:
            events = sel.select()
            for key, mask in events:
                callback = key.data
                try:
                    callback(key.fileobj,mask)
                except:
                    sel.unregister(key.fileobj)
                    key.fileobj.close()