# Copyright 2014 Bevbot LLC, All Rights Reserved
#
# This file is part of the Pykeg package of the Kegbot project.
# For more information on Pykeg or Kegbot, see http://kegbot.org/
#
# Pykeg 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.
#
# Pykeg 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 Pykeg.  If not, see <http://www.gnu.org/licenses/>.

import atexit
import os
import signal
import sys
from optparse import make_option
from django.core.management.base import BaseCommand
from pykeg.util.runner import Runner

def progbar(title, pos, total, width=40):
    """Prints a progress bar to stdout.

    Args
      title: title to show next to progress bar
      pos: current position (integer)
      total: total positions (integer)
      width: width of the progres bar, in characters
    """
    if not total:
        chars = width
    else:
        chars = int((float(pos)/total)*width)
    rem = width - chars
    inner = '+'*chars + ' '*rem
    sys.stdout.write('%-30s  [%s] %i/%i\r' % (title, inner, pos, total))
    sys.stdout.flush()


def check_and_create_pid_file(pid_file):
    if os.path.exists(pid_file):
        print 'Error: already running ({})'.format(pid_file)
        sys.exit(1)

    f = open(pid_file, 'w')
    f.write('{}\n'.format(os.getpid()))
    f.close()

class check_pidfile(object):
    """Context manager that creates a pidfile, or fails if it exists."""
    def __init__(self, pid_file):
        self.pid_file = pid_file

    def __enter__(self):
        if os.path.exists(self.pid_file):
            raise RuntimeError('Error: already running ({})'.format(self.pid_file))
        f = open(self.pid_file, 'w')
        f.write('{}\n'.format(os.getpid()))
        f.close()

    def __exit__(self, exc_type, exc_val, exc_tb):
        os.unlink(self.pid_file)

class RunnerCommand(BaseCommand):
    """Command that runs several subcommands as a watched group."""
    requires_model_validation = False

    option_list = BaseCommand.option_list + (
        make_option('--logs_dir', action='store', dest='logs_dir', default='',
            help='Specifies the directory for log files.  If empty, logging disabled.'),
        make_option('--pidfile_dir', action='store', dest='pidfile_dir', default='/tmp',
            help='PID file for this program.'),
    )

    pidfile_name = None

    def get_commands(self, options):
        """Returns iterable of (command_name, command)."""
        raise NotImplementedError

    def handle(self, *args, **options):
        pidfile = os.path.join(options['pidfile_dir'], self.pidfile_name)
        with check_pidfile(pidfile):
            r = Runner()
            def exit_fn(signum, frame):
                os.kill(-os.getpgrp(), signal.SIGKILL)
            signal.signal(signal.SIGTERM, exit_fn)
            for command_name, command in self.get_commands(options):
                r.add_command(command_name, command)
            try:
                r.run()
            except KeyboardInterrupt:
                r.abort()
                sys.exit(1)

@@ -3066,16 +3066,17 @@
 unner()%0A
+%0A
         
@@ -3127,45 +3127,96 @@
     
-os.kill(-os.getpgrp(), signal.SIGKILL
+r.abort()%0A                sys.exit(1)%0A%0A            signal.signal(signal.SIGTERM, exit_fn
 )%0A  
@@ -3241,36 +3241,35 @@
 ignal(signal.SIG
-TERM
+INT
 , exit_fn)%0A     
@@ -3255,32 +3255,33 @@
 IGINT, exit_fn)%0A
+%0A
             for 
@@ -3390,137 +3390,25 @@
 nd)%0A
-            try:%0A                r.run()%0A            except KeyboardInterrupt:%0A                r.abort()%0A                sys.exit(1
+%0A            r.run(
 )%0A

Use sigterm for killing children.