#!/usr/bin/env python
#
# Copyright 2012 Jim Lawton. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import sys
import logging
import optparse

import gdocs

session = None
commands = {}

def command(funcname):
    global commands
    commands[funcname.func_name] = funcname
    return funcname

@command
def help(argv):
    """Print help message.
gdrive help [COMMAND]

If no argument is specified, print a list of commands with a short description of each. If a command is specified, print help on that command.
"""
    if not argv:
        return usage()
    for cmd in commands:
        if cmd == argv[0]:
            print commands[cmd].__doc__.split('\n', 1)[1]
            return
    print >>sys.stderr, "Unknown command '%s'" % argv[0]

def usage():
    "Print usage."
    print "Google Drive command-line interface"
    print
    print "Commands:"
    print
    print "Note: use gdrive help <command> to view usage for a specific command."
    print
    lines = []
    cmdlist = commands.keys()
    cmdlist.sort()
    for cmd in cmdlist:
        lines.append((cmd, commands[cmd].__doc__.splitlines()[0]))
    space = max(len(line[0]) + 3 for line in lines)
    for line in lines:
        print " %-*s%s" % (space, line[0], line[1])
    print

@command
def start(argv):
    """Start GDrive daemon.
gdrive start

Starts the GDrive daemon, gdrived, if it is not already running.

"""
    sys.exit("Not implemented!")

@command
def stop(argv):
    """Stop GDrive daemon.
gdrive stop

Stops the GDrive daemon, gdrived, if it is running.

"""
    sys.exit("Not implemented!")

@command
def userinfo(argv):
    """Print user info.
gdrive userinfo

Prints user information on the currently authenticated Google Drive account..

"""
    print session.getUserData()
    
@command
def list(argv):
    """List folder contents.
gdrive list <path>

Lists the contents of the specified path. If no path is specified, then the root folder is assumed.

"""
    root = argv
    if argv == None:
        root = '/'
    folders, files = session.readFolder(root)
    for path in folders:
        print path
    for path in files:
        print path, session.getFileSize(path)

@command
def update(argv):
    """Update a folder.
gdrive update <path>

Update the contents of the specified path, recursively. If no path is specified, then the entire GDrive will be updated.

"""
    root = argv
    if argv == None:
        root = '/'
    session.update(root)

def _parseArgs():
    "Parse command-line arguments."
    helpStr = """
%prog [options] 

Utility to access Google Drive.

"""
    parser = optparse.OptionParser(description=helpStr)
    parser.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False,                   help='Turn on extra logging')
    parser.add_option('-d', '--debug',   dest='debug',   action='store_true', default=False,                   help='Turn on debug logging')
    (options, args) = parser.parse_args()
    return (options, args)


def main(argv):
    "Main function."

    session = gdocs.DocsSession()
    if session == None:
        sys.exit("Error, could not create Google Docs session!")

    (opts, args) = _parseArgs()

    if opts.debug:
        logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
    elif opts.verbose:
        logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
    else:
        logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.WARNING)

    cmdfound = False
    i = 0
    for i in range(len(argv)):
        if argv[i] in commands:
            cmdfound = True
            break

    if not cmdfound:
        usage()
        return None

    res = None
    if argv[i] in commands:
        res = commands[argv[i]](argv[i+1:])

    return res


if __name__ == "__main__":
    result = main(sys.argv)
    if result != None:
        sys.exit(result)

@@ -710,16 +710,29 @@
 nds = %7B%7D
+%0Aaliases = %7B%7D
 %0A%0Adef co
@@ -745,56 +745,215 @@
 func
-name
 ):%0A    
-global commands%0A    commands%5Bfuncname
+if not func.__doc__:%0A        sys.exit(%22Error: commands must have formatted docstrings!%22)%0A    commands%5Bfunc.func_name%5D = func%0A    func_aliases = %5Balias for alias in aliases.iterkeys() if aliases%5Balias%5D
 .fun
@@ -962,40 +962,343 @@
 name
-%5D
  
+=
 = func
-name%0A    return funcname
+.func_name%5D%0A    if func_aliases:%0A        func.__doc__ += %22Aliases: %25s%22 %25 %22,%22.join(func_aliases)%0A    return func%0A%0Adef alias(name):%0A    def decorator(func):%0A        if name in commands:%0A            sys.exit(%22Error, this alias has the same name as a command!%22)%0A        aliases%5Bname%5D = func%0A        return func%0A    return decorator
 %0A%0A@c
@@ -2774,24 +2774,37 @@
   %0A@command%0A
+@alias(%22ls%22)%0A
 def list(arg
@@ -3182,24 +3182,37 @@
 )%0A%0A@command%0A
+@alias(%22up%22)%0A
 def update(a

Add aliases for commands, I prefer ls to list :-).