import os, os.path
import sys
import re
from sjrpc.client import SimpleRpcClient
import cccli
import pprint
from cccli import printer
from cccli.clierror import *

class Command(object):

    def __init__(self, argv, cli):
        # check argv
        if len(argv) < 1:
            raise BadCommand()
        # check valid command chars
        if not re.match("^[a-zA-Z0-9]+", argv[0]):
            raise BadCommmand("Invalid command name")
        cmdlist = [ x[4:] for x in dir(self) if x.startswith("cmd_") ]
        matchlist = [ x for x in cmdlist if re.match("%s.+"%argv[0], x) ]
        if argv[0] in cmdlist:
            pass
        elif len(matchlist) == 1:
            argv[0] = matchlist[0]
        elif len(matchlist) > 1:
            raise BadCommand("Too many command: %s"%", ".join(matchlist))
        else:
            raise BadCommand()
        self._cmd = getattr(self, "cmd_%s"%argv[0])
        self._argv = argv
        self.cli = cli

    @classmethod
    def usage(cls, cmdname):
        '''Return usage of a command'''
        fname = "cmd_%s"%cmdname
        if not hasattr(cls, fname):
            raise BadArgument(cmdname)
        if hasattr(getattr(cls, fname), "usage"):
            return getattr(getattr(cls, fname), "usage")
        return ""

    def call(self):
        '''Run command'''
        if re.match("^[a-zA-Z0-9]+$", self._argv[0]):
            name = "cmd_%s"%self._argv[0]
            if hasattr(self, name):
                cmd = getattr(self, name)
                return cmd(self._argv)
        raise BadCommand(self._argv[0])

    def cmd_exit(self, argv):
        '''Quit application with respect'''
        raise SystemExit()
    cmd_exit.usage = "exit"
    cmd_exit.desc = "Quit application with respect"

    def cmd_quit(self, argv):
        '''Quit application with respect'''
        raise SystemExit()
    cmd_quit.usage = "quit"
    cmd_quit.desc = "Quit application with respect"

    def cmd_version(self, argv):
        '''Print cli version'''
        printer.out(cccli.version)
    cmd_version.usage = "version"
    cmd_version.desc = "Print cli version"

    def cmd_usage(self, argv):
        '''Print usage of a command'''
        if len(argv) != 2:
            raise BadArgument()
        usage = Command.usage(argv[1])
        if usage != "":
            printer.out("usage: %s"%usage)
        else:
            printer.out("No usage.")
    cmd_usage.usage = "usage [command]"
    cmd_usage.desc = "Print usage of a command"

    def cmd_help(self, argv):
        '''Print help'''
        if len(argv) == 1:
            # build command list
            cmdlist = list()
            doclist = list()
            for x in dir(self):
                m = re.match("^cmd_([a-zA-Z0-9]+)$", x)
                if m:
                    cmdlist.append(m.group(1))
                    if hasattr(getattr(self, x), "__doc__"):
                        doclist.append(getattr(getattr(self, x), "__doc__"))
            # printing commands list
            width = max(map(len, cmdlist)) + 3
            printer.out("%sCommands:%s"%(printer.color["lwhite"], printer.color["reset"]))
            for c, d in zip(cmdlist, doclist):
                line = "%s"%c
                line = line.ljust(width,)
                line += "- %s"%d
                printer.out(line)
        elif len(argv) == 2:
            fname = "cmd_%s"%argv[1]
            if hasattr(self, fname):
                if hasattr(getattr(self, fname), "__doc__"):
                    printer.out("Description: %s"%getattr(getattr(self, fname), "__doc__"))
                if hasattr(getattr(self, fname), "usage"):
                    printer.out("Usage: %s"%getattr(getattr(self, fname), "usage"))
                if hasattr(getattr(self, fname), "details"):
                    Printer.out("Details: %s"%getattr(getattr(self, fname), "details"))
            else:
                raise BadArgument(argv[1])
        else:
            raise BadArgument()
    cmd_help.usage = "help [command]"
    cmd_help.desc = "Print help about a command"

    def cmd_alias(self, argv):
        '''Show or create alias'''
        if len(argv) == 1:
            for n, v in self.cli.alias.items():
                printer.out("%s=%s"%(n, v))
        elif len(argv) == 2:
            if argv[1] not in self.cli.alias:
                raise BadArgument(argv[1])
            printer.out("%s=%s"%(argv[1], self.cli.alias[argv[1]]))
        elif len(argv) == 3:
            self.cli.alias[argv[1]] = argv[2]
            self.cli.alias.save()
        else:
            raise BadArgument()
    cmd_alias.usage = "alias [name] [value]"
    cmd_alias.desc = "Show or create aliases"

    def cmd_unalias(self, argv):
        '''Remove an alias'''
        if len(argv) != 2:
            raise BadArgument()
        if argv[1] not in self.cli.alias:
            raise BadArgument("%s: No such alias"%argv[1])
        del self.cli.alias[argv[1]]
        self.cli.alias.save()
    cmd_unalias.usage = "unalias [name]"
    cmd_unalias.desc = "Remove an aliases"

    def cmd_rcmd(self, argv):
        '''Show remote commands'''
        for cmds in self.cli.rpc.list_commands():
            printer.out("%s"%cmds["name"])
    cmd_rcmd.usage = "rcmd"
    cmd_rcmd.desc = "Print remote command list"

    def cmd_list(self, argv):
        '''List something'''
        if len(argv) == 1:
            argv.append("")
        items = self.cli.rpc.list(str.join("", argv[1:]))
        for item in items:
            pprint.pprint(item)
            #for key, val in item.items():
            #    printer.out("%s: %s "%(key, val))
    cmd_list.usage = "list [tags]"
    cmd_list.desc = "Print information about tags"