import sys
import argparse
import datetime
import logging
import inspect
import itertools
from library.python.nyt import client as nyt_client
import yt.wrapper as yt
from datacloud.config.yt import PRODUCTION_ROOT
from datacloud.logging.logging_config import configure_logging, LogLevel
from datacloud.dev_utils.status_db.db import StatusDB
from datacloud.key_manager.key_helpers import get_key, set_default_storage
from datacloud.dev_utils.time.patterns import FMT_DATE_HM
from datacloud.launcher.scenario import fast, slow


logger = logging.getLogger(__name__)


def use_yt_token(token_name):
    """ Forced change global yt token """
    yt_token = get_key("yt_tokens", token_name, default=None)
    if yt_token is None:
        logger.warning("Unknown token %s. Use YT_TOKEN env variable instead of it.", token_name)
        return
    logger.info("Use %s token for YT", token_name)
    yt.config["token"] = yt_token


def main():
    # [DO NOT REMOVE] required right here to run C++ on YT
    nyt_client.initialize(sys.argv)
    now = datetime.datetime.now()
    date_time = now.strftime(FMT_DATE_HM)
    command_arguments = argparse.ArgumentParser(description="Util to launch build in python yt programs")
    command_arguments.add_argument(
        '--program',
        help="one of detect_ready_ProfileDump | process_ProfileDump | detect_ready_day_logs | ..."
    )
    command_arguments.add_argument(
        '--date-hour-min',
        default=date_time,
        help="date hour to launch like '2016-09-27 00:05'"
    )
    command_arguments.add_argument('--yt-root', default=None,
                                   help='yt folder where script will take input and work')
    command_arguments.add_argument('--force', default=False, action='store_true',
                                   help='run/start if if not all data ready')
    command_arguments.add_argument('--yt-token-name', default='default',
                                   help='use token with this name for YT operations')
    command_arguments.add_argument('--keys-path', default=None,
                                   help='read keys from this directory')
    command_arguments.add_argument('--limit', default=None,
                                   help='max limit for run/change state')
    command_arguments.add_argument('--days', default=None,
                                   help='days for detect_ready')
    command_arguments.add_argument('--use-yt-cfg', default=False, action='store_true',
                                   help='use cfg from yt dynamic tables')
    command_arguments.add_argument('--yt-cluster', default='hahn',
                                   help='use yt cluster to work on')
    command_arguments.add_argument('--impulse', default=None,
                                   help='substring to search in task path')
    command_arguments.add_argument('--worker', default='main',
                                   help='worker id')
    args = command_arguments.parse_args()

    configure_logging(log_level=LogLevel.INFO)
    yt.config.set_proxy(args.yt_cluster)

    if args.keys_path is not None:
        set_default_storage(path=args.keys_path)

    if args.yt_token_name:
        use_yt_token(args.yt_token_name)

    status_db = StatusDB(table_path=yt.ypath_join(PRODUCTION_ROOT, 'new-status-db'))

    for name, func in itertools.chain(
            inspect.getmembers(slow, inspect.isfunction),
            inspect.getmembers(fast, inspect.isfunction),
            ):
        if name == args.program:
            return func(status_db, args)

    logger.error('Unknown program %s', args.program)


if __name__ == '__main__':
    main()
