#!/usr/bin/python3
 
import sys
from gobject import MainLoop
from dbus.mainloop.glib import DBusGMainLoop
from ubuntuone.platform.credentials import CredentialsManagementTool
import ubuntuone.couch.auth as auth
import urllib.request, urllib.parse, urllib.error
import json
import mimetypes

class U1Files():

    def login(self):
        # Login
        global _login_success
        _login_success = False
       
        DBusGMainLoop(set_as_default=True)
        loop = MainLoop()
       
        def quit(result):
            global _login_success
            loop.quit()
            if result:
                _login_success = True
       
        cd = CredentialsManagementTool()
        d = cd.login()
        d.addCallbacks(quit)
        loop.run()
        if not _login_success:
            sys.exit(1)
        return _login_success
     
    def logout(self):
        # Logout
        DBusGMainLoop(set_as_default=True)
        loop = MainLoop()
       
        def quit(result):
            loop.quit()
       
        cd = CredentialsManagementTool()
        d = cd.clear_credentials()
        d.addCallbacks(quit)
        loop.run()
     
    def create_volume(self, path):
        # Create directory
        base = "https://one.ubuntu.com/api/file_storage/v1/volumes/~/"
        url = base + urllib.parse.quote(path)
        auth.request(url, http_method="PUT")
        answer = auth.request(url)
        status = int(answer[0].get('status'))
        return status

    def put(self, local, remote):
        # Create remote path (which contains volume path)
        base = "https://one.ubuntu.com/api/file_storage/v1/~/"
        answer = auth.request(base + urllib.parse.quote(remote),
                              http_method="PUT",
                              request_body='{"kind":"file"}')
        node = json.loads(answer[1])
        
        # Read info about local file
        data = bytearray(open(local, 'rb').read())
        size = len(data)
        content_type = mimetypes.guess_type(local)[0]
        content_type = content_type or 'application/octet-stream'
        headers = {"Content-Length": str(size),
                   "Content-Type": content_type}
       
        # Upload content of local file to content_path from original response
        base = "https://files.one.ubuntu.com"
        url = base + urllib.parse.quote(node.get('content_path'), safe="/~")
        auth.request(url, http_method="PUT",
                     headers=headers, request_body=data)

        sha1, size, status = self.query(remote)
        return status
     
    def get(self, remote, local):
        # Request metadata
        base = "https://one.ubuntu.com/api/file_storage/v1/~/"
        answer = auth.request(base + urllib.parse.quote(remote))
        node = json.loads(answer[1])
        status = int(answer[0].get('status'))
        
        # Request content
        base = "https://files.one.ubuntu.com"
        url = base + urllib.parse.quote(node.get('content_path'), safe="/~")
        answer = auth.request(url)
        f = open(local, 'wb')
        f.write(answer[1])
        return status

    def get_children(self, path):
        # Request children metadata
        base = "https://one.ubuntu.com/api/file_storage/v1/~/"
        url = base + urllib.parse.quote(path) + "?include_children=true"
        answer = auth.request(url)
        status = int(answer[0].get('status'))
        # Create file list out of json data
        filelist = []
        node = json.loads(answer[1])
        if node.get('has_children') == True:
            for child in node.get('children'):
                child_path = urllib.parse.unquote(child.get('path')).lstrip('/')
                filelist += [child_path]
        return filelist, status
     
    def query(self, path):
        # Request metadata
        base = "https://one.ubuntu.com/api/file_storage/v1/~/"
        url = base + urllib.parse.quote(path)
        answer = auth.request(url)
        node = json.loads(answer[1])
        status = int(answer[0].get('status'))
        # Print interesting info
        return node.get('hash'), node.get('size'), status
     
    def delete(self, path):
        # Delete file
        base = "https://one.ubuntu.com/api/file_storage/v1/~/"
        url = base + urllib.parse.quote(path)
        answer = auth.request(url)
        status = int(answer[0].get('status'))
        auth.request(url, http_method="DELETE")
        return status

if __name__ == "__main__":
    f = U1Files()

    if len(sys.argv) <= 1:
        print("Need more arguments")
        sys.exit(1)

    if sys.argv[1] == "delete":
        f.login()
        f.delete(sys.argv[2])

    if sys.argv[1] == "login":
        f.login()

    if sys.argv[1] == "get":
        f.login()
        print(f.get(sys.argv[2], sys.argv[3]))

    if sys.argv[1] == "list":
        f.login()
        print(f.get_children(sys.argv[2]))

    if sys.argv[1] == "put":
        f.login()
        print(f.put(sys.argv[2], sys.argv[3]))

    if sys.argv[1] == "query":
        f.login()
        print(f.query(sys.argv[2]))

    if sys.argv[1] == "create-volume":
        f.login()
        print(f.create_volume(sys.argv[2]))

    if sys.argv[1] == "logout":
        f.logout()
