#!/usr/bin/env python
#-*-coding:utf-8-*-

import os, sys
import argparse
from collections import defaultdict

import luigi
import luiti.manager as manager
curr_dir  = os.getcwd()

def bool_type(arg1):
    arg2 = arg1.lower()
    if arg2 == 'false': return False
    if arg2 == 'true':  return True
    raise ValueError("[err value] %s" % arg1)


# 1. parser
parser_main    = argparse.ArgumentParser(description="Luiti tasks manager.")
subparsers     = parser_main.add_subparsers(title="subcommands", description='valid subcommands',)

# 1.1.
parser_ls   = subparsers.add_parser('ls', help=u"list all current luiti tasks.")
parser_ls.add_argument("--project-dir",   help=u"force to use another project directory.", default=curr_dir)

# 1.2.
parser_info = subparsers.add_parser('info', help=u"show a detailed task.")
parser_info.add_argument('--task-name',     help=u"必须指定任务名称，比如 --task-name=Redmine5954ParentReportWeek",   required=True, )
parser_info.add_argument("--project-dir",   help=u"force use another project directory.", default=curr_dir)

# 1.3.
parser_clean   = subparsers.add_parser('clean', help=u"manage files that outputed by luiti tasks.")
parser_clean.add_argument('--task-name',         help=u"必须指定任务名称，比如 --task-name=Redmine5954ParentReportWeek",   required=True, )
parser_clean.add_argument('--date-range',        help=u"必须指定时间周期，比如 --date-range=20141001-20141015",            required=True, )
parser_clean.add_argument('--dry',               help=u"可以指定 **假运行** 模式 , 比如 --dry=true。",                     default=True,  choices=[True, False], type=bool_type)
parser_clean.add_argument('--dep',               help=u"可以指定 --dep=true，这样就会寻找依赖于当前Task之上的任务",        default=False, choices=[True, False], type=bool_type)
parser_clean.add_argument('--force',             help=u"强制删除文件",                                                     default=False, choices=[True, False], type=bool_type)
parser_clean.add_argument("--project-dir",       help=u"force use another project directory.", default=curr_dir)

# 1.4
parser_run = subparsers.add_parser('run', help=u"run a luiti task.")
parser_run.add_argument('--task-name',           help=u"必须指定任务名称，比如 --task-name=Redmine5954ParentReportWeek",   required=True, )
parser_run.add_argument('--date-value',          help=u"必须指定具体时间，比如 --date-value=2014-09-01T00:00:01+08:00 。后面的时区信息是必须的。",   required=True, )
parser_run.add_argument("--project-dir",         help=u"force use another project directory.", default=curr_dir)

if len(sys.argv) == 1:
    parser_main.print_help()
    exit(0)


args_main  = parser_main.parse_args()
subcommand = sys.argv[1]

# NOTE modify sys.path in here.
luiti_tasks_dirs = manager.Path.find_all_luiti_tasks_parent_dirs(args_main.project_dir)
result           = manager.Loader.load_all_tasks(*luiti_tasks_dirs)
all_task_classes = [i1['task_cls'] for i1 in result['success']]

if "project_dir" in args_main:
    manager.Path.ProjectDir = args_main.project_dir

#import pdb; pdb.set_trace()
if "task_name" in args_main:
    curr_task = manager.load_a_task_by_name(args_main.task_name)

if subcommand == "ls": manager.Table.print_all_tasks(result)

if subcommand == "info":
    dep_tasks_on_curr_task = manager.find_dep_on_tasks(curr_task, all_task_classes)
    manager.Table.print_task_info(curr_task, dep_tasks_on_curr_task)

if subcommand == "clean":
    dep_tasks_on_curr_task = [curr_task]
    if args_main.dep:
        dep_tasks_on_curr_task = manager.find_dep_on_tasks(curr_task, all_task_classes)
    dep_file_to_task_instances = manager.get_all_date_file_to_task_instances(args_main.date_range, dep_tasks_on_curr_task)

    manager.print_files_by_task_cls_and_date_range(
                            curr_task,
                            args_main,
                            {
                                "dep_file_to_task_instances" : dep_file_to_task_instances,
                                "task_classes_count"         : len(dep_tasks_on_curr_task),
                                "dep_tasks_on_curr_task"     : dep_tasks_on_curr_task,
                            })

    if args_main.dry:
        print "\nTips: just set --dry=false to soft-delete theses files.\n"
    else:
        manager.soft_delete_files(*dep_file_to_task_instances.keys())

if subcommand == "run":

    # 1. 把参数修复为 luigi 接受的参数，即把只有 luiti 依赖的参数去除。
    old = sys.argv[:]
    def fetch_keys(parser1): return parser1.__dict__['_option_string_actions'].keys()
    luigi_keep_opts = ["--date-value"]
    luiti_only_opts = subparsers.choices.keys() + fetch_keys(parser_ls) + fetch_keys(parser_clean) + fetch_keys(parser_run)
    luiti_only_opts = [i1 for i1 in luiti_only_opts if i1 not in  luigi_keep_opts]
    delete_argv_idxes = set([])
    for idx1, arg1 in enumerate(sys.argv):
        if idx1 in delete_argv_idxes: continue
        # 1. 排除 tasks, files, run 等
        if (not arg1.startswith("--")) and (arg1 in luiti_only_opts):
            delete_argv_idxes.add(idx1)
            continue
        # 2. 处理 --task-name 等参数
        if "=" in arg1:
            arg2, val2 = arg1.split("=", 1)
            if arg2 in luiti_only_opts:
                delete_argv_idxes.add(idx1)
        else:
            if (arg1 in luiti_only_opts) and (not arg1 in luigi_keep_opts):
                delete_argv_idxes.add(idx1)
                delete_argv_idxes.add(idx1 + 1)
    sys.argv = [arg1 for idx1, arg1 in enumerate(sys.argv) if idx1 not in delete_argv_idxes]

    # 2. run it!
    luigi.run(main_task_cls=curr_task)
