# cmdserver.py

# Demo code that is not Pythonwin related, but too good to throw away...

import _thread
import sys
import traceback

import win32api
from pywin.framework import winout


class ThreadWriter:
    "Assign an instance to sys.stdout for per-thread printing objects - Courtesy Guido!"

    def __init__(self):
        "Constructor -- initialize the table of writers"
        self.writers = {}
        self.origStdOut = None

    def register(self, writer):
        "Register the writer for the current thread"
        self.writers[_thread.get_ident()] = writer
        if self.origStdOut is None:
            self.origStdOut = sys.stdout
            sys.stdout = self

    def unregister(self):
        "Remove the writer for the current thread, if any"
        try:
            del self.writers[_thread.get_ident()]
        except KeyError:
            pass
        if len(self.writers) == 0:
            sys.stdout = self.origStdOut
            self.origStdOut = None

    def getwriter(self):
        "Return the current thread's writer, default sys.stdout"
        self.writers.get(_thread.get_ident(), self.origStdOut)

    def write(self, str):
        "Write to the current thread's writer, default sys.stdout"
        self.getwriter().write(str)


def Test():
    num = 1
    while num < 1000:
        print("Hello there no", num)
        win32api.Sleep(50)
        num += 1


class flags:
    SERVER_BEST = 0
    SERVER_IMMEDIATE = 1
    SERVER_THREAD = 2
    SERVER_PROCESS = 3


def StartServer(cmd, title=None, bCloseOnEnd=0, serverFlags=flags.SERVER_BEST):
    out = winout.WindowOutput(title, None, winout.flags.WQ_IDLE)
    if not title:
        title = cmd
    out.Create(title)
    # 	ServerThread((out, cmd, title, bCloseOnEnd))
    # 	out = sys.stdout
    _thread.start_new_thread(ServerThread, (out, cmd, title, bCloseOnEnd))


def ServerThread(myout, cmd, title, bCloseOnEnd):
    try:
        writer.register(myout)
        print('Executing "%s"\n' % cmd)
        bOK = 1
        try:
            import __main__

            exec(cmd + "\n", __main__.__dict__)
        except:
            bOK = 0
        if bOK:
            print("Command terminated without errors.")
        else:
            t, v, tb = sys.exc_info()
            print(t, ": ", v)
            traceback.print_tb(tb)
            tb = None  # prevent a cycle
            print("Command terminated with an unhandled exception")
        writer.unregister()
        if bOK and bCloseOnEnd:
            myout.frame.DestroyWindow()

    # Unhandled exception of any kind in a thread kills the gui!
    except:
        t, v, tb = sys.exc_info()
        print(t, ": ", v)
        traceback.print_tb(tb)
        tb = None
        print("Thread failed")


# assist for reloading (when debugging) - use only 1 tracer object,
# else a large chain of tracer objects will exist.
try:
    writer
except NameError:
    writer = ThreadWriter()
if __name__ == "__main__":
    import demoutils

    demoutils.NotAScript()
