#!/usr/bin/env python
#coding=utf8


import os
import argparse

import pkg_resources

from kolekto.printer import printer
from kolekto.exceptions import KolektoRuntimeError
from kolekto.config import parse_config


def find_root():
    """ Find the root path of the Kolekto tree from the current working directory.

    If function doesn't find a Kolekto tree, it returns the cwd.
    :return: the path to the root directory of Kolekto tree.
    """

    cwd = os.getcwd()
    while cwd != '/':
        config = os.path.join(cwd, '.kolekto')
        if os.path.exists(config):
            return cwd
        else:
            cwd, _ = os.path.split(cwd)
    else:
        return os.getcwd()


def main():
    """ Binary entry-point.
    """
    aparser = argparse.ArgumentParser()
    aparser.add_argument('-t', '--tree', default=find_root())
    aparser.add_argument('-e', '--editor', default=os.environ.get('EDITOR', 'vim'))
    aparser.add_argument('-d', '--debug', action='store_true', default=False)
    aparser.add_argument('-V', '--verbose', action='store_true', default=False)
    aparser_subs = aparser.add_subparsers(help='Kolekto commands')

    # Register all the kolekto commands:
    commands = {}
    for entrypoint in pkg_resources.iter_entry_points(group='kolekto.commands'):
        command_class = entrypoint.load()
        commands[entrypoint.name] = command_class(entrypoint.name, aparser_subs)
        commands[entrypoint.name].prepare()

    # Parse the command line arguments:
    args = aparser.parse_args()

    # Configure the main printer:
    printer.configure(verbose=args.verbose, debug=args.debug, editor=args.editor)

    # Parse configuration:
    try:
        config = parse_config(os.path.join(args.tree, '.kolekto', 'config'))
    except IOError as err:
        if err.errno == 2:
            config = None
        else:
            raise

    # Execute the selected command:
    printer.debug('Executing command {cmd}', cmd=args.command)
    try:
        args.command(args, config)
    except KolektoRuntimeError as err:
        printer.p('Error: {error}', error=err)
    except KeyboardInterrupt:
        printer.p('Interrupted by user.')

if __name__ == '__main__':
    main()
