# w.c.s. - web application for online forms
# Copyright (C) 2005-2014  Entr'ouvert
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.

import tempfile
import time
import os

from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from wcs.qommon.publisher import get_publisher_class

from wcs.qommon.vendor import locket
from wcs.qommon.cron import cron_worker
from wcs.wf.jump import JUMP_TIMEOUT_INTERVAL


class Command(BaseCommand):
    help = 'Execute cronjobs'

    def add_arguments(self, parser):
        parser.set_defaults(verbosity=0)
        parser.add_argument('--force-job', dest='force_job', action='store_true',
            help='Run even if DISABLE_CRON_JOBS is set in settings')
        parser.add_argument('--job', dest='job_name', metavar='NAME')

    def handle(self, verbosity, **options):
        if getattr(settings, 'DISABLE_CRON_JOBS', False) and not options['force_job']:
            if verbosity > 1:
                print('Command is ignored because DISABLE_CRON_JOBS is set in settings')
            return
        lockfile = os.path.join(tempfile.gettempdir(), 'wcs-cron-in-progress.lock')
        try:
            with locket.lock_file(lockfile, timeout=0):
                if verbosity > 2:
                    print('cron start (lock %s)' % lockfile)
                now = time.localtime()
                publisher_class = get_publisher_class()
                publisher_class.register_cronjobs()
                publisher = publisher_class.create_publisher()
                app_dir = publisher.app_dir
                for hostname in publisher.get_tenants():
                    if verbosity > 1:
                        print('cron work on %s' % hostname)
                    publisher.app_dir = os.path.join(app_dir, hostname)
                    cron_worker(publisher, now, job_name=options.get('job_name'))
            if verbosity > 2:
                print('cron end (release lock %s)' % lockfile)
        except locket.LockError:
            age = int(time.time() - os.stat(lockfile).st_mtime)
            if age > JUMP_TIMEOUT_INTERVAL*10:
                raise CommandError(
                    'can not start cron job, locked by %s for %s seconds (seems old)' %
                    (lockfile, age))
            if verbosity > 0:
                print('can not start cron job, locked by %s for %s seconds' % (lockfile, age))
