

import code
import os.path
import popen2
import sys
import time

from eventlet import api
from eventlet import logutil

from mulib import mu
from mulib import eventrouter

import simplejson

from indra import llsd


class ShellConsole(eventrouter.Router):
    transforms = os.path.join(os.path.dirname(__file__), 'shellconsole.js')
    stylesheet = os.path.join(os.path.dirname(__file__), 'shellconsole.css')

    def __init__(self, my_host, root):
        self.my_host = my_host
        self.interactor = code.InteractiveConsole(root)
        self.logsucker = logutil.LineLogger(self.emit)
        self.reset_collector()
        self.partial_lines = ''
        self.ps1_prompt = '>>> '
        self.ps2_prompt = '... '
        self.prompt = self.ps1_prompt
        eventrouter.Router.__init__(self)

    def event_connect(self, target):
        return [target.peer_name_string(), "shellconsole running on %s" % (self.my_host, )]

    def reset_collector(self):
        self.collector = []

    def emit(self, line):
        self.collector.append(line)

    def post_key_typed(self, data):
        my_name = data['my_name']
        current_input = data['current_input']
        for target in self.targets:
            if target.peer_name_string() != my_name:
                target.msg('key-typed', [my_name, current_input])

    def post_console_input(self, data_map):
        self.reset_collector()
        command_id = time.time()
        cmd = str(data_map['input'])
        print "Running command", command_id, cmd
        self.broadcast('input-line', [data_map['my_name'], self.prompt, cmd])
        stderr = self.saved_stderr = sys.stderr
        stdout = self.saved_stdout = sys.stdout

        try:
            sys.stderr = self.logsucker
            sys.stdout = self.logsucker
            result = self.interactor.runsource(self.partial_lines + cmd)
        finally:
            sys.stderr, sys.stdout = self.saved_stderr, self.saved_stdout
        if not result:
            self.prompt = self.ps1_prompt
            self.partial_lines = ''
        else:
            self.prompt = self.ps2_prompt
            self.partial_lines += cmd + '\n'
        for output_line in self.collector:
            print output_line
            self.broadcast('output-line', output_line)
        print "Finished shell command", `result`, command_id

    def handle_post(self, req):
        action = req.get_query('post', 'default')
        data = req.read_body()
        data = simplejson.loads(data)
        meth = getattr(self, 'post_' + action, None)(data)
        req.write(mu.xml(''))

