#!/usr/bin/env python
""" Assignment management tool for school.
Usage:
  taksman.py (-h | --help)
  taksman.py add <entry>
  taksman.py course
  taksman.py date
  taksman.py debug

Examples:
  taksman.py add 033-reading

Options:
  -h, --help
"""

import os
import errno
import re
from pprint import pprint
from docopt import docopt

def show_by_course(tasks):
    courses = set(tasks[name].get('course') for name in tasks)
    courses -= set([None])
    courses = sorted(courses)

    for course in courses:
        print
        print "Course: %s" % course
        course_tasks = filter(
            lambda name: tasks[name].get('course') == course,
            tasks)
        for name in course_tasks:
            print "> %s" % name

def read_tasks(db_root):
    """ Load tasks from db. """
    entry_names = os.listdir(os.path.join(db_root, "entry"))
    entry_paths = {filename: os.path.join(db_root, "entry", filename) for filename in entry_names}
    tasks = {name: read_task(entry_paths[name]) for name in entry_names}
    return tasks

def read_task(filepath):
    """ Read a task from a file. """
    task = {}
    task['body'] = ""

    with open(filepath, 'r') as f:
        reading_headers = True
        for line in f.readlines():
            header_match = re.match(r"(?P<field>\w+): +(?P<value>.*)$", line)
            if reading_headers and header_match:
                field = header_match.group('field')
                value = header_match.group('value')
                assert field != 'body'
                assert field not in task
                task[field] = value.rstrip()
            else:
                reading_headers = False
                task['body'] += line.rstrip() + "\n"

    task['body'] = task['body'].rstrip()

    return task

def ensure_db(db_root):
    """ Make the storage directories exist. """
    mkdir_p(os.path.join(db_root, "entry"))
    mkdir_p(os.path.join(db_root, "done"))
    mkdir_p(os.path.join(db_root, "template"))

def mkdir_p(path):
    """ no error if existing, make parent directories as needed """
    try:
        os.makedirs(path)
    except OSError as exc:
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise

if __name__ == "__main__":
    db_root = "tasks"
    ensure_db(db_root)
    tasks = read_tasks(db_root)

    arguments = docopt(__doc__)
    if arguments['debug']:
        pprint(tasks)
    elif arguments['add']:
        raise Exception("not implemented")
    elif arguments['course']:
        show_by_course(tasks)
    elif arguments['course']:
        raise Exception("not implemented")
    else:
        print "Whoops, unhandled input."

@@ -117,16 +117,42 @@
 %3Centry%3E%0A
+  taksman.py done %3Centry%3E%0A
   taksma
@@ -163,16 +163,16 @@
  course%0A
-
   taksma
@@ -239,16 +239,95 @@
 -reading
+   create a new task entry%0A  taksman.py done %3Centry%3E      mark an entry as done
 %0A%0AOption
@@ -347,16 +347,27 @@
 lp%0A%22%22%22%0A%0A
+import sys%0A
 import o
@@ -381,16 +381,34 @@
 t errno%0A
+import subprocess%0A
 import r
@@ -552,19 +552,57 @@
  tasks)%0A
-
    
+ # Note: None can be in this set%0A    #
  courses
@@ -2407,16 +2407,128 @@
  raise%0A%0A
+def edit_file(filepath):%0A    editor = os.environ.get('EDITOR', 'nano')%0A    subprocess.call(%5Beditor, filepath%5D)%0A%0A
 if __nam
@@ -2744,41 +2744,627 @@
     
-raise Exception(%22not implemented%22
+name = arguments%5B'%3Centry%3E'%5D%0A        if name in tasks:%0A            print %22%25s already in tasks%22 %25 name%0A            sys.exit(-1)%0A        filepath = os.path.join(db_root, 'entry', name)%0A        edit_file(filepath)%0A        print %22%25s saved to %25s%22 %25 (name, filepath)%0A    elif arguments%5B'done'%5D:%0A        name = arguments%5B'%3Centry%3E'%5D%0A        if name not in tasks:%0A            print %22%25s not in tasks%22 %25 name%0A            sys.exit(-1)%0A        filepath = os.path.join(db_root, 'entry', name)%0A        newpath = os.path.join(db_root, 'done', name)%0A        os.rename(filepath, newpath)%0A        print %22%25s archived to %25s%22 %25 (name, newpath
 )%0A  
@@ -3433,37 +3433,35 @@
 elif arguments%5B'
-cours
+dat
 e'%5D:%0A        rai

add 'done' command