#!/usr/bin/python

import sys
import readline
import code
import codeop
import argparse
import logging
import os
import atexit
import __builtin__


try:

    import _preamble

except ImportError:

    sys.exc_clear()


import pythonect

# Pythonect Console


class PythonectCompile(codeop.Compile):

    def __init__(self):

        codeop.Compile.__init__(self)

    def __call__(self, source, filename, symbol):

        if source[-1] == '\\':
            return None

        return source.replace('\\\n', '')


class PythonectCommandCompiler(codeop.CommandCompiler):

    def __init__(self):

        codeop.CommandCompiler.__init__(self)

        self.compiler = PythonectCompile()


class PythonectInteractiveConsole(code.InteractiveConsole):

    def __init__(self, locals=None, histfile=os.path.expanduser("~/.pythonect_history")):

        code.InteractiveConsole.__init__(self, locals)

        self.compile = PythonectCommandCompiler()

        self.init_history(histfile)

    def init_history(self, histfile):

        try:

            readline.read_history_file(histfile)

        except IOError:

            pass

        atexit.register(self.save_history, histfile)

    def save_history(self, histfile):

        readline.write_history_file(histfile)

    # This is a cut & paste from /usr/lib/python2.7/code.py
    # Except we're not calling `exec` statement

    def runcode(self, code_):

        try:

            return_value = pythonect.eval(code_, {}, self.locals)

            # Meaningful Return Value?

            if return_value is not None:

                # String?

                if isinstance(return_value, basestring):

                    # Enclose in single quotes

                    return_value = "'" + return_value + "'"

                self.write(str(return_value) + '\n')

                # Keep return_value for further reference or reset to None?

                if return_value is False or return_value is True:

                    # Reset locals to None

                    self.locals['_'] = None

        except SystemExit:

            raise

        except:

            self.showtraceback()

        else:

            if code.softspace(sys.stdout, 0):

                print


def main():

    verbose_levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]

    # Pythonect's Banner

    banner = "Pythonect %s" % pythonect.__version__

    # Parse command-line arguments

    parser = argparse.ArgumentParser(sys.argv)

    parser.add_argument('script', metavar='file', nargs='?', type=argparse.FileType('rt'), help='program read from script file')
    parser.add_argument('arg', metavar='arg', nargs='*', help='arguments passed to program in sys.argv[1:]')
    parser.add_argument('--verbose', '-v', action='count', default=0)
    parser.add_argument('--version', '-V', action='version', version=banner)
    parser.add_argument('--distributed', action='store_true', help='Run in distributed mode')
    parser.add_argument('--server', '-S', nargs=1, default=None, help='Use specified rpc_manager for distributed mode')

    args = parser.parse_args()

    # Setup logging level

    logging.basicConfig(level=verbose_levels[args.verbose % 4], format="%(filename)10s:%(lineno)4d:%(message)s")

    # Adjust sys.argv, make sys.argv[1] as sys.argv[0], sys.argv[2] as sys.argv[1] and etc.

    sys.argv = sys.argv[1:]

    if not sys.argv:

        sys.argv = ['']

    # Check distributed mode, set rpc_manager to one of: existing rpc_manager, new process running development rpc_manager,
    # or None - to run in local mode.

    if args.distributed:

        if args.server:

            rpc_manager = pythonect._XMLRPCManager(args.server)

        else:

            rpc_manager = pythonect._XMLRPCManager()

    else:

        rpc_manager = None

    
    globals_dict = rpc_manager.globals_dict if rpc_manager else {}
    
    # Script-mode (i.e. ./pythonect script or #!/usr/bin/env pythonect)

    if args.script:
        
        pythonect.eval(args.script.read().replace('\\\n', ''), globals_dict, {})
        #pythonect.eval(args.script.read().replace('\\\n', ''), {}, {})

        args.script.close()

    # Interactive-mode (i.e. ./pythonect)

    else:

        # Add current working directory to sys.path

        sys.path.insert(0, os.getcwd())

        #TODO - pass the globals dict to the interactive console

        PythonectInteractiveConsole().interact(banner)

    return 0


# Entry Point

if __name__ == "__main__":

    sys.exit(main())
