#! /usr/bin/env python3

from random import SystemRandom as generator
from subprocess import Popen, PIPE
# from subprocess import check_output
import os
import string
import sys

TASK = '/usr/bin/task'
SPRINT_KEY_FILE = 'sprint_key'
KANBAN = 'kanban'


def get_sprint_key_filename():
    taskrc = open('%s/.taskrc' % os.environ['HOME'])
    for line in taskrc:
        if line.find('data.location=') is 0:
            data_location = line.split('=')[1].strip()
    taskrc.close()
    return '%s/%s' % (data_location, SPRINT_KEY_FILE)


def get_key(must_exist=False):
    sprint_key_file = get_sprint_key_filename()
    if os.path.isfile(sprint_key_file):
        sprint = open(sprint_key_file, 'r')
        key = sprint.read()
        sprint.close()
        return key
    else:
        if must_exist:
            print("ERR: Sprint has not started yet!")
            sys.exit(2)
        else:
            return None


def print_header(title):
    start = 24
    end = 70 - start - len(title)
    header = ' ' * start + title + ' ' * end
    print("\033[7m%s\033[7m\033[0m\n" % header)


def help(exit_status=0):
    script_fullpath = os.path.realpath(__file__)
    script_dir = script_fullpath[:script_fullpath.rfind('/') + 1]
    if exit_status is not 0:
        print("ERROR: Wrong Invocation")
    help_text = open('%s/.help_text' % script_dir)
    for l in help_text:
        print(l)
    sys.exit(0)


######################################################################
# Global actions to open and close sprints
######################################################################


def open_sprint(__args__):
    sprint_key_file = get_sprint_key_filename()
    if os.path.isfile(sprint_key_file):
        print("ERROR: Sprint already open!")
        sys.exit(1)
    else:
        sprint = open(sprint_key_file, 'w')
        key = ''.join(generator().choice(string.ascii_letters) for _ in range(8))
        sprint.write(key)
        sprint.close()
        print("Sprint started: %s" % key)


def close_sprint(force):
    key = get_key(True)
    out, err = Popen("%s +%s count" % (TASK, key),
                     stdout=PIPE, stderr=PIPE, shell=True).communicate()
    open_tasks = int(out.decode().strip())
    if open_tasks is 0:
        print("Removing sprint key")
        os.remove(get_sprint_key_filename())
    else:
        print("WARN: There are still %s tasks to be done.\n" % open_tasks)
        print("Use:\n\t%s close force\n\nto force sprint close" % KANBAN)
        sys.exit(101)


def key_sprint(_args_):
    key = get_key(False)
    if key is None:
        print("WARN:There is no sprint open yet")
        sys.exit(102)
    else:
        print(key)


######################################################################
# Actions perfomed on task ids
######################################################################


def add_to_ready(taskid):
    key = get_key(True)
    os.system("%s %s mod +%s +ready" % (TASK, taskid, key))


def add_to_wip(taskid):
    os.system("%s %s start -ready" % (TASK, taskid))


def add_to_done(taskid):
    os.system("%s %s done" % (TASK, taskid))


def block(taskid):
    os.system("%s %s mod +BLOCKED" (TASK, taskid))


def unblock(taskid):
    os.system("%s %s mod -BLOCKED" (TASK, taskid))

######################################################################
# Reporting actions
######################################################################


def list_backlog():
    key = get_key(False)
    if key is None:
        print("WARN: There is no sprint open yet")
        os.system("%s next" % TASK)
    else:
        os.system("%s -%s" % (TASK, key))


def list_with_tag(tag):
    key = get_key(True)
    os.system("%s +%s +%s" % (TASK, key, tag))


def list_blocked():
    list_with_tag('BLOCKED')


def list_ready():
    list_with_tag('ready')


def list_wip():
    key = get_key(True)
    os.system("%s +%s active" % (TASK, key))


def list_done():
    key = get_key(True)
    os.system("%s +%s completed" % (TASK, key))


def burndown():
    key = get_key(True)
    os.system("%s +%s burndown.daily" % (TASK, key))


def list_all():
    key = get_key(True)
    print_header('Ready')
    os.system("%s +%s +ready" % (TASK, key))
    print_header('WIP')
    os.system("%s +%s active" % (TASK, key))
    print_header('Done')
    os.system("%s +%s completed" % (TASK, key))

######################################################################
# Main procedure
######################################################################


def main():
    sprint_actions = {
        'open': open_sprint,
        'close': close_sprint,
        'key': key_sprint
    }
    reports = {
        'help': help,
        'backlog': list_backlog,
        'ready': list_ready,
        'blocked': list_blocked,
        'completed': list_done,
        'wip': list_wip,
        'burndown': burndown,
        'view': list_all
    }
    actions = {
        'add': add_to_ready,
        'start': add_to_wip,
        'done': add_to_done,
        'block': block,
        'unblock': unblock
    }
    DEFAULT = 'view'
    param = DEFAULT if len(sys.argv) < 2 else sys.argv[1]
    if param.isdigit():
        task_id = int(param)
        action = None if len(sys.argv) < 3 else sys.argv[2]
        if action in actions.keys():
            actions[action](task_id)
    else:
        command = param
        if command in reports.keys():
            reports[command]()
        elif command in sprint_actions.keys():
            sprint_actions[command](sys.argv)


if __name__ == '__main__':
        main()
