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

import os
import sys
import argparse

from luiti import luigi, manager
lc = luigi.luiti_config
curr_dir = os.getcwd()


def bool_type(arg1):
    """ a convertor. """
    str_to_val_map = {"false": False, "true": True}
    val1 = str_to_val_map.get(arg1.lower(), None)
    assert val1 is not None, ValueError("[err value] %s" % arg1)
    return val1


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

parser_ls = subparsers.add_parser('ls', help=u"list all current luiti tasks.")

parser_new = subparsers.add_parser('new', help=u"create a new luiti project.")
# TODO remove argument key, just value only.
parser_new.add_argument(
    '--project-name',
    help=u"必须指定项目名称，比如 --project-name=table_base", required=True, )

parser_gene = subparsers.add_parser(
    'generate', help=u"generate a new luiti task python file.")

parser_info = subparsers.add_parser('info', help=u"show a detailed task.")

parser_clean = subparsers.add_parser(
    'clean', help=u"manage files that outputed by luiti tasks.")

parser_run = subparsers.add_parser('run', help=u"run a luiti task.")

parser_webui = subparsers.add_parser('webui', help=u"start a luiti DAG visualiser.")
parser_webui.add_argument(
    '--luiti-packages', default="",
    help=u"Add luiti packages, separated by comma.", required=False, )
parser_webui.add_argument(
    '--host', default="0.0.0.0",
    help=u"webui server host", required=False, )
parser_webui.add_argument(
    '--port', default=8082,
    help=u"webui server port", required=False, )


for parser_1 in [parser_ls, parser_gene, parser_info,
                 parser_clean, parser_run, parser_webui]:
    parser_1.add_argument(
        "--project-dir",
        help=u"force use another project directory.",
        default=curr_dir)

    if parser_1 not in [parser_ls, parser_new, parser_webui]:
        parser_1.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_run.add_argument(
    '--date-value',
    help=u"必须指定具体时间，比如 --date-value=2014-09-01T00:00:01+08:00 。后面的时区信息是必须的。",
    required=True, )


# check arguments
if len(sys.argv) == 1:
    parser_main.print_help()
    exit(0)
else:
    args_main = parser_main.parse_args()
    subcommand = sys.argv[1]

    if "project_dir" in args_main:
        lc.curr_project_dir = args_main.project_dir
lc.curr_project_dir = lc.curr_project_dir or curr_dir


# check valid project.
if subcommand != "new":  # not new a project
    lc.fix_project_dir()

    if not os.path.exists(os.path.join(lc.curr_project_dir, "luiti_tasks")):
        print u"""
    Current work directory '%s' has no sub directory 'luiti_tasks', make sure
    you have already `cd path/to/your/luiti/project/` .
        """ % (lc.curr_project_dir)
        exit(1)

if ("task_name" in args_main) and (subcommand not in ["generate"]):
    curr_task = manager.load_a_task_by_name(args_main.task_name)


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

if subcommand == "new":
    manager.new_a_project(args_main.project_name)
if subcommand == "generate":
    manager.generate_a_task(args_main.task_name, lc.curr_project_dir)

if subcommand == "info":
    manager.Table.print_task_info(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, manager.ld.all_task_classes)
        dep_tasks_on_curr_task.insert(0, curr_task)
    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 依赖的参数去除。
    manager.SysArgv.convert_to_luigi_accepted_argv(subparsers)

    # 2. run it!
    # luigi.run(main_task_cls=curr_task)  # old style
    from luiti.schedule import SensorSchedule
    # luiti only need these two parameters. Other parameters can be passed by Shell environment variables.
    SensorSchedule.run(curr_task, args_main.date_value)


if subcommand == "webui":
    # add other luiti packages.
    for luiti_package in args_main.luiti_packages.split(","):
        luigi.plug_packages(luiti_package)

    from luiti.daemon import run
    run(args_main.host, args_main.port)
