import re
from datetime import datetime

from command import CommandRegistry, split_arguments
from commands import core, scheduler
from interactive import *
from little_shit import get_source, check_target

__registry__ = cr = CommandRegistry()

_cmd_subscribe = 'subscribe.subscribe'
_scheduler_job_id_prefix = _cmd_subscribe + '_'


@cr.register('subscribe', '订阅')
@cr.restrict(group_admin_only=True)
@split_arguments(maxsplit=1)
@check_target
def subscribe(args_text, ctx_msg, argv=None, internal=False, allow_interactive=True):
    source = get_source(ctx_msg)
    if not internal and allow_interactive and has_session(source, _cmd_subscribe):
        # Already in a session, no need to pass in data,
        # because the interactive version of this command will take care of it
        return _subscribe_interactively(args_text, ctx_msg, source, None)

    data = {}
    if argv:
        m = re.match('([0-1]\d|[2][0-3])(?::|:)?([0-5]\d)', argv[0])
        if not m:
            # Got command but no time
            data['command'] = args_text
        else:
            # Got time
            data['hour'], data['minute'] = m.group(1), m.group(2)
            if len(argv) == 2:
                # Got command
                data['command'] = argv[1]

    if not internal and allow_interactive:
        if data.keys() != {'command', 'hour', 'minute'}:
            # First visit and data is not enough
            return _subscribe_interactively(args_text, ctx_msg, source, data)

    # Got both time and command, do the job!
    hour, minute = data['hour'], data['minute']
    command = data['command']
    job = scheduler.add_job(
        '-H %s -M %s --multi %s %s' % (
        hour, minute, _scheduler_job_id_prefix + str(int(datetime.now().timestamp())), command),
        ctx_msg, internal=True
    )
    if internal:
        return job
    if job:
        # Succeeded to add a job
        reply = '订阅成功,我会在每天 %s 推送哦~' % ':'.join((hour, minute))
    else:
        reply = '订阅失败,可能后台出了点小问题~'

    core.echo(reply, ctx_msg, internal)


@cr.register('subscribe_list', 'subscribe-list', '订阅列表', '查看订阅', '查看所有订阅', '所有订阅')
@cr.restrict(group_admin_only=True)
@check_target
def subscribe_list(_, ctx_msg, internal=False):
    jobs = sorted(filter(
        lambda j: j.id.startswith(_scheduler_job_id_prefix),
        scheduler.list_jobs('', ctx_msg, internal=True)
    ), key=lambda j: j.id)

    if internal:
        return jobs

    if not jobs:
        core.echo('暂时还没有订阅哦~', ctx_msg)
        return

    for index, job in enumerate(jobs):
        command_list = job.kwargs['command_list']
        reply = 'ID:' + job.id[len(_scheduler_job_id_prefix):] + '\n'
        reply += '下次推送时间:\n%s\n' % job.next_run_time.strftime('%Y-%m-%d %H:%M')
        reply += '命令:\n'
        reply += scheduler.convert_command_list_to_str(command_list)
        core.echo(reply, ctx_msg)
    core.echo('以上~', ctx_msg)


@cr.register('unsubscribe', '取消订阅')
@cr.restrict(group_admin_only=True)
@split_arguments()
@check_target
def unsubscribe(_, ctx_msg, argv=None, internal=False):
    if not argv:
        core.echo('请在命令名后指定要取消订阅的 ID(多个 ID、ID 和命令名之间用空格隔开)哦~\n\n'
                  '你可以通过「查看所有订阅」命令来查看所有订阅项目的 ID', ctx_msg, internal)
        return

    result = []
    for job_id_without_prefix in argv:
        result.append(scheduler.remove_job(_scheduler_job_id_prefix + job_id_without_prefix, ctx_msg, internal=True))

    if internal:
        return result[0] if len(result) == 1 else result

    if all(result):
        core.echo('取消订阅成功~', ctx_msg, internal)
    else:
        core.echo('可能有订阅 ID 没有找到,请使用「查看所有订阅」命令来检查哦~',
                  ctx_msg, internal)


def _subscribe_interactively(args_text, ctx_msg, source, data):
    sess = get_session(source, _cmd_subscribe)
    if data:
        sess.data.update(data)

    state_command = 1
    state_time = 2
    state_finish = -1
    if sess.state == state_command:
        if not args_text.strip():
            core.echo('你输入的命令不正确,请重新发送订阅命令哦~', ctx_msg)
            sess.state = state_finish
        else:
            sess.data['command'] = args_text
    elif sess.state == state_time:
        m = re.match('([0-1]\d|[2][0-3])(?::|:)?([0-5]\d)', args_text.strip())
        if not m:
            core.echo('你输入的时间格式不正确,请重新发送订阅命令哦~', ctx_msg)
            sess.state = state_finish
        else:
            sess.data['hour'], sess.data['minute'] = m.group(1), m.group(2)

    if sess.state == state_finish:
        remove_session(source, _cmd_subscribe)
        return

    if 'command' not in sess.data:
        # Ask for command
        core.echo(
            '请输入你需要订阅的命令(包括所需的参数),每行一条,不需要加开头的斜杠哦~\n\n'
            '例如(序号后的):\n'
            '(1) 天气 南京\n'
            '(2) 知乎日报\n'
            '(3) 历史上的今天',
            ctx_msg
        )
        sess.state = state_command
        return

    if 'hour' not in sess.data or 'minute' not in sess.data:
        # Ask for time
        core.echo('请输入你需要推送的时间,格式如 22:00', ctx_msg)
        sess.state = state_time
        return

    subscribe(
        '', ctx_msg,
        argv=[':'.join((sess.data['hour'], sess.data['minute'])), sess.data['command']],
        allow_interactive=False
    )
    remove_session(source, _cmd_subscribe)