def add_file(*args, **kwargs):
    if len(args) == 0 or '--help' in ''.join(args):
        map(print, [
            'About: This command adds a file to Dropbox by encrypting and signing the file using your private key.',
            '',
            'Usage: $ dcc add <path,...>',
            '',
            'Specify one or more paths delimited by spaces. Paths to files can be absolute or relative but must',
            'point to a file. Paths can refer to files outside of this directory.',
        ])
        return 1
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo(
    )
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    for arg in args:
        if len(arg) > 0:
            full_path = normpath(join(getcwd(), arg))
            if isfile(full_path):
                with open(full_path, 'r') as source_file:
                    file_uuid = vfs.add_file(full_path)
                    upload_file(
                        api_token, container_name,
                        encrypt(source_file.read(), encryption_key,
                                signing_key), file_uuid)
                    print('[DONE] `%s` ~> `%s`' % (full_path, file_uuid))
    save_vfs(api_token, container_name, vfs, encryption_key, signing_key)
    return 0
def show_info(*args, **kwargs):
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo()
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    print('Encryption Key:', b64encode(encryption_key))
    print('Signing Key:', b64encode(signing_key))
    print('API Token:', api_token)
    print('Container Name:', '%s (%s)' % ( human_container_name, container_name ))
    print('File Count:', len(vfs))
    return 0
def show_tree(*args, **kwargs):
    if '--help' in ''.join(args):
        map(print, [
            'About: This command outputs a tree view of the virtual file system.',
        ])
        return 1
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo()
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    vfs.print_tree()
    return 0
def show_info(*args, **kwargs):
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo(
    )
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    print('Encryption Key:', b64encode(encryption_key))
    print('Signing Key:', b64encode(signing_key))
    print('API Token:', api_token)
    print('Container Name:',
          '%s (%s)' % (human_container_name, container_name))
    print('File Count:', len(vfs))
    return 0
def show_tree(*args, **kwargs):
    if '--help' in ''.join(args):
        map(print, [
            'About: This command outputs a tree view of the virtual file system.',
        ])
        return 1
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo(
    )
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    vfs.print_tree()
    return 0
def sync_files(*args, **kwargs):
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo()
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    for _, (file_name, path, file_uuid) in vfs.files.iteritems():
        path = path[:-len(basename(path))]
        print('Attempting to write `%s` ~> `%s`' % (file_name, path))
        if not exists(path):
            makedirs(path)
            print(' [OK] Created Path `%s`' % path)
        decrypted_file = decrypt(download_file(api_token, container_name, file_uuid), encryption_key, signing_key)
        print(' [OK] Downloaded and decrypted `%s`' % file_uuid)
        with open(join(path, file_name), 'w+') as output_file:
            output_file.write(decrypted_file)
            print(' [OK] Wrote file `%s`' % file_name)
    return 0
def sync_files(*args, **kwargs):
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo(
    )
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    for _, (file_name, path, file_uuid) in vfs.files.iteritems():
        path = path[:-len(basename(path))]
        print('Attempting to write `%s` ~> `%s`' % (file_name, path))
        if not exists(path):
            makedirs(path)
            print(' [OK] Created Path `%s`' % path)
        decrypted_file = decrypt(
            download_file(api_token, container_name, file_uuid),
            encryption_key, signing_key)
        print(' [OK] Downloaded and decrypted `%s`' % file_uuid)
        with open(join(path, file_name), 'w+') as output_file:
            output_file.write(decrypted_file)
            print(' [OK] Wrote file `%s`' % file_name)
    return 0
def show_list(*args, **kwargs):
    args_joined = ' '.join(args)
    if len(args) == 0 or '--help' in args_joined:
        map(print, [
            'About: This command interactively browses the virtual file system.',
            '', 'Usage: $ dcc list <path> (--no-interactive)', '',
            'Use `--no-interactive` to output specified path. Path must be provided and in the virtual file system.',
            'If using interactive mode specify `:q` to quit the interactivivity loop.'
        ])
        return 1
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo(
    )
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    path = args[0].strip()
    while True:
        vfs.print_list_files(path)
        if '--no-interactive' in args_joined:
            break
        else:
            path = raw_input('> ').strip()
            if path == ':q':
                break
    return 0
def add_file(*args, **kwargs):
    if len(args) == 0 or '--help' in ''.join(args):
        map(print, [
            'About: This command adds a file to Dropbox by encrypting and signing the file using your private key.',
            '',
            'Usage: $ dcc add <path,...>',
            '',
            'Specify one or more paths delimited by spaces. Paths to files can be absolute or relative but must',
            'point to a file. Paths can refer to files outside of this directory.',
        ])
        return 1
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo()
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    for arg in args:
        if len(arg) > 0:
            full_path = normpath(join(getcwd(), arg))
            if isfile(full_path):
                with open(full_path, 'r') as source_file:
                    file_uuid = vfs.add_file(full_path)
                    upload_file(api_token, container_name, encrypt(source_file.read(), encryption_key, signing_key), file_uuid)
                    print('[DONE] `%s` ~> `%s`' % (full_path, file_uuid))
    save_vfs(api_token, container_name, vfs, encryption_key, signing_key)
    return 0
def get_file(*args, **kwargs):
    if len(args) == 0 or '--help' in ''.join(args):
        map(print, [
            'About: This command retrieves a file from the virtual file system if it exists.',
            '', 'Usage: $ dcc get <virtual path> (<local path>)', '',
            'By default this will output the contents of the file to standard output unless the `<local path>` is specified.',
            'The `<local path>` can optionally include the filename otherwise the name of the file when uploaded will be used.'
        ])
        return 1
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo(
    )
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    vfs_exists, data = vfs.get_file_data(args[0])
    if not vfs_exists:
        print('Error: The path `%s` does not exist.' % args[0])
        return 1
    if len(args) >= 2:  # if we have virtual path and local path
        local_path = normpath(join(getcwd(), args[1].strip()))
        if len(local_path) > 0:
            local_filename = basename(local_path)
            if len(local_filename) > 0 and '.' not in local_filename:
                local_filename = ''
            if len(local_filename) > 0:
                local_path = local_path[:-len(local_filename)]
            else:
                local_filename = data[0]
            if not exists(local_path):
                makedirs(local_path)
            with open(join(local_path, local_filename), 'w+') as output_file:
                content = download_file(api_token, container_name, data[2])
                output_file.write(decrypt(content, encryption_key,
                                          signing_key))
                return 0
    # else we do not have the local path, we need to output to standard out
    content = download_file(api_token, container_name, data[2])
    print(decrypt(content, encryption_key, signing_key))
    return 0
def get_file(*args, **kwargs):
    if len(args) == 0 or '--help' in ''.join(args):
        map(print, [
            'About: This command retrieves a file from the virtual file system if it exists.',
            '',
            'Usage: $ dcc get <virtual path> (<local path>)',
            '',
            'By default this will output the contents of the file to standard output unless the `<local path>` is specified.',
            'The `<local path>` can optionally include the filename otherwise the name of the file when uploaded will be used.'
        ])
        return 1
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo()
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    vfs_exists, data = vfs.get_file_data(args[0])
    if not vfs_exists:
        print('Error: The path `%s` does not exist.' % args[0])
        return 1
    if len(args) >= 2: # if we have virtual path and local path
        local_path = normpath(join(getcwd(), args[1].strip()))
        if len(local_path) > 0:
            local_filename = basename(local_path)
            if len(local_filename) > 0 and '.' not in local_filename:
                local_filename = ''
            if len(local_filename) > 0:
                local_path = local_path[:-len(local_filename)]
            else:
                local_filename = data[0]
            if not exists(local_path):
                makedirs(local_path)
            with open(join(local_path, local_filename), 'w+') as output_file:
                content = download_file(api_token, container_name, data[2])
                output_file.write(decrypt(content, encryption_key, signing_key))
                return 0
    # else we do not have the local path, we need to output to standard out
    content = download_file(api_token, container_name, data[2])
    print(decrypt(content, encryption_key, signing_key))
    return 0
def show_list(*args, **kwargs):
    args_joined = ' '.join(args)
    if len(args) == 0 or '--help' in args_joined:
        map(print, [
            'About: This command interactively browses the virtual file system.',
            '',
            'Usage: $ dcc list <path> (--no-interactive)',
            '',
            'Use `--no-interactive` to output specified path. Path must be provided and in the virtual file system.',
            'If using interactive mode specify `:q` to quit the interactivivity loop.'
        ])
        return 1
    encryption_key, signing_key, api_token, human_container_name, container_name = prompt_userinfo()
    vfs = load_vfs(api_token, container_name, encryption_key, signing_key)
    path = args[0].strip()
    while True:
        vfs.print_list_files(path)
        if '--no-interactive' in args_joined:
            break
        else:
            path = raw_input('> ').strip()
            if path == ':q':
                break
    return 0