#!/usr/bin/env python

import argparse
import logging
import os
import sys
from distutils.version import StrictVersion # pylint: disable=no-name-in-module

INVALID_SETTINGS_ERROR = "Error: You must either set the environmental "\
    "variable DJANGO_SETTINGS_MODULE or pass it as "\
    "an argument"

logger = logging.getLogger('chroniker')

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description=('Run cron jobs for a Django '
                     'project using '
                     'django-chroniker.'),
        epilog=("NOTE: You must provide one of "
                "the following: settings or "
                "project_dir.")
    )
    parser.add_argument('-s', metavar='settings', type=str, nargs='?', dest="settings", help=('Django settings module. You must provide.'))
    parser.add_argument('-p', metavar='project_dir', type=str, nargs='?', dest="project_dir", help='Path to project directory')
    parser.add_argument('-e', metavar='virtualenv', type=str, nargs='?', dest="virtualenv", help=('Path to virtual environment "activate_this.py" file'))
    parser.add_argument('-q', action='store_true', dest="quite", default=False, help="Suppress output")
    parser.add_argument('-l', action='store_true', dest="loud", default=False, help="Display more output")
    parser.add_argument('--jobs', dest="jobs", default='', help='A comma-delimited list of job ids to limit executions to.')
    args = parser.parse_args()

    log_level = logging.INFO
    if args.quite:
        logging.disable(logging.CRITICAL)
        log_level = logging.CRITICAL
    elif args.loud:
        log_level = logging.DEBUG

    logging.basicConfig(stream=sys.stdout, format="[%(levelname)-8s] %(message)s")
    logger.setLevel(log_level)

    # If we're supposed to be running in a virtualenv, activate it
    if args.virtualenv:
        virtualenv = os.path.abspath(args.virtualenv)
        assert os.path.isfile(virtualenv), 'Virtualenv file "%s" does not exist.' % virtualenv
        with open(virtualenv, encoding='utf8') as fin:
            exec(fin.read(), dict(__file__=virtualenv)) # pylint: disable=exec-used

    # Now setup django
    project_dir = args.project_dir
    if project_dir:
        project_dir = os.path.abspath(args.project_dir)
        if not os.path.isdir(project_dir):
            logger.error("Error: Project directory does not exist: %s", project_dir)

        # Make sure that the project is on the path
        sys.path.append(project_dir)
        sys.path.append(os.path.join(project_dir, '../'))

    settings = args.settings
    if not settings and 'DJANGO_SETTINGS_MODULE' not in os.environ:
        if not project_dir:
            # Well, we can't do anything...
            logger.error(INVALID_SETTINGS_ERROR)
            sys.exit(0)

        # We'll assume the settings file is in the project directory
        settings = "%s.settings" % os.path.basename(project_dir)

    # Now assign the settings if necessary.
    if settings:
        os.environ['DJANGO_SETTINGS_MODULE'] = settings

    jobs = args.jobs #(args.jobs or '').split(',')

    logger.debug("Project dir: %s", project_dir)
    logger.debug("Settings mod: %s", settings)

    # We should be good to go now
    import django
    DJANGO_VERSION = StrictVersion(django.get_version())
    if DJANGO_VERSION >= StrictVersion('1.7'):
        django.setup()
    from django.core.management import call_command

    for extra_path in [None, '.', '..']:
        try:
            if extra_path:
                # If the previous import failed, try checking a few additional paths.
                sys.path.append(extra_path)
            settings = __import__(os.environ['DJANGO_SETTINGS_MODULE'])
            break
        except Exception as e:
            if extra_path == '..':
                sys.stderr.write("Error: Could not find Django settings\n")
                sys.stderr.write(str(e))
                sys.stderr.write(str('\n'))
                sys.exit(0)

    call_command('cron', jobs=jobs)
