# w.c.s. - web application for online forms
# Copyright (C) 2005-2010  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/>.

# Most of this code is copied from the shell command [1] of the project Django
# release 1.4. Many thanks to them.
#
# [1]: file django/core/management/commands/shell.py

from __future__ import print_function

import os.path

from ..qommon.ctl import Command, make_option

class CmdShell(Command):
    '''Launch a shell and initialize a publisher on a given host'''

    name = 'shell'
    def __init__(self):
        Command.__init__(self, [
                make_option('--plain', action='store_true',
                            dest='plain', default=False) ])

    def execute(self, base_options, sub_options, args):
        from .. import publisher
        self.config.remove_option('main', 'error_log')
        publisher.WcsPublisher.configure(self.config)
        publisher = publisher.WcsPublisher.create_publisher(
                register_tld_names=False)
        publisher.app_dir = os.path.join(publisher.APP_DIR, args[0])
        if not os.path.exists(publisher.app_dir):
            print('Application directory %r does not exist.' % publisher.app_dir)
            raise SystemExit(1)
        publisher.set_config()
        try:
            if sub_options.plain:
                # Don't bother loading IPython, because the user wants plain Python.
                raise ImportError
            self.run_shell()
        except ImportError:
            import code
            # Set up a dictionary to serve as the environment for the shell, so
            # that tab completion works on objects that are imported at runtime.
            # See ticket 5082.
            imported_objects = {}
            try: # Try activating rlcompleter, because it's handy.
                import readline
            except ImportError:
                pass
            else:
                # We don't have to wrap the following import in a 'try', because
                # we already know 'readline' was imported successfully.
                import rlcompleter
                readline.set_completer(rlcompleter.Completer(imported_objects).complete)
                readline.parse_and_bind("tab:complete")

            # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
            # conventions and get $PYTHONSTARTUP first then import user.
            if not sub_options.plain:
                pythonrc = os.environ.get("PYTHONSTARTUP")
                if pythonrc and os.path.isfile(pythonrc):
                    try:
                        execfile(pythonrc)
                    except NameError:
                        pass
                # This will import .pythonrc.py as a side-effect
                import user
            code.interact(local=imported_objects)

    shells = [ 'ipython', 'bpython' ]

    def ipython(self):
        try:
            from IPython import embed
            embed()
        except ImportError:
            # IPython < 0.11
            # Explicitly pass an empty list as arguments, because otherwise
            # IPython would use sys.argv from this script.
            try:
                from IPython.Shell import IPShell
                shell = IPShell(argv=[])
                shell.mainloop()
            except ImportError:
                # IPython not found at all, raise ImportError
                raise

    def bpython(self):
        import bpython
        bpython.embed()

    def run_shell(self):
        for shell in self.shells:
            try:
                return getattr(self, shell)()
            except ImportError:
                pass
        raise ImportError

CmdShell.register()
