#!/usr/bin/env python

"""Example trivial telnet client using TkSocket

History:
2009-07-10 ROwen    Removed an inline conditional statement to be Python 2.4 compatible.
"""
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
import re, os, platform, pwd, sys, time
from datetime import datetime

import tkinter
import RO.Comm.TCPConnection
import RO.Wdg


class TCPClient(tkinter.Frame):
    def __init__(self, master, addr, port=None, cmdrName=None):
        tkinter.Frame.__init__(self, master)
        self.master = master
        self.displayRegexp = None       # regexp must match to display output in window
        self.noDisplayRegexp = None     # regexp must not match to display output in window

        self.logWdg = RO.Wdg.LogWdg(
            master = self,
            maxLines = 1000,
        )
        self.logWdg.grid(row=0, column=0, sticky="nsew")
        
        self.bottomWdg = tkinter.Frame(self, background="")
        self.bottomWdg.grid(row=1, column=0, sticky="ew")

        self.prefixWdg = RO.Wdg.CmdWdg(
            master = self.bottomWdg,
            maxCmds = 10,
            cmdFunc = self.prefixCmd,
            relief="flat",
            width=15
        )

        self.cmdWdg = RO.Wdg.CmdWdg(
            master = self.bottomWdg,
            maxCmds = 100,
            cmdFunc = self.doCmd,
        )

        self.reWdg = RO.Wdg.CmdWdg(
            master = self.bottomWdg,
            maxCmds = 10,
            cmdFunc = self.doRe,
            width=20

        )

        self.prefixWdg.pack(fill="x", side="left"); self.prefix = None
        self.cmdWdg.pack(fill="x", side="left", expand=True)
        tkinter.Label(self.bottomWdg, text=" Filter actors:").pack(side="left")
        self.reWdg.pack(side="right")

        self.cmdrName = "%s.%s" % ("client", 
                                   cmdrName if cmdrName else pwd.getpwuid(os.getuid()).pw_name)
        self.cmdID = 1
    
        self.conn = RO.Comm.TCPConnection.TCPConnection(
            host = addr,
            port = port,
            readLines = True,
            stateCallback = self.connState,
            readCallback = self.connRead,
        )
        self.conn.connect()
        
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.doCmd('hub setUsername %s' % (self.cmdrName))
        
    def connState(self, sock):
        state, reason = sock.fullState
        if reason:
            self.logMsg("*** Socket %s: %s" % (state, reason))
        else:
            self.logMsg("*** Socket %s" % (state,))
    
    def connRead(self, sock, readStr):
        self.logMsg(readStr)

    def doRe(self, actorsList):
        """Set a new regexp"""

        actorsList = actorsList.split()

        actorsToDisplay =    [x     for x in actorsList if not re.search(r"^!", x)]
        actorsToNotDisplay = [x[1:] for x in actorsList if     re.search(r"^!", x)]

        if actorsToDisplay:
            self.displayRegexp = r"^\S+\s+\d+\s+(%s)\s+(\S+)\s+" % "|".join(actorsToDisplay)
        else:
            self.displayRegexp = None

        if actorsToNotDisplay:
            self.noDisplayRegexp = r"^\S+\s+\d+\s+(%s)\s+(\S+)\s+" % "|".join(actorsToNotDisplay)
        else:
            self.noDisplayRegexp = None
            
        self.setTitle(" ".join(actorsToDisplay), " ".join(actorsToNotDisplay))

    def doCmd(self, cmd):
        if not cmd:
            self.logMsg('<cr>')
            return

        cmd = "%s %d %s" % (self.cmdrName, self.cmdID, cmd)
        self.cmdID += 1
        if not self.conn.isConnected:
            self.logMsg("*** Not connected")
        self.conn.writeLine(cmd)

        if self.prefix:
            self.cmdWdg.set(self.prefix + " ")
            self.cmdWdg.icursor("end")

    def prefixCmd(self, prefix):
        self.prefixWdg.clear()
        self.prefix = prefix.strip()
        self.prefixWdg.set(self.prefix)

        self.cmdWdg.clear()
        if self.prefix:
            self.cmdWdg.insert(0, self.prefix + " ")
            self.cmdWdg.icursor("end")
        self.cmdWdg.focus_force()

    def timeStamp(self, t=None):
        if t == None:
            t = datetime.now()

        return t.strftime("%H:%M:%S.%f")
    
    def logMsg(self, msg):
        r"""Append msg to log, with terminating \n"""

        if ((self.displayRegexp   and not re.search(self.displayRegexp,   msg))  or
            (self.noDisplayRegexp and     re.search(self.noDisplayRegexp, msg))) and msg != "<cr>":

            if False:
                print('"%s"' % msg, self.displayRegexp, (self.displayRegexp   and not re.search(self.displayRegexp,   msg)), \
                      self.noDisplayRegexp, (self.noDisplayRegexp and     re.search(self.noDisplayRegexp, msg)))
            return

        self.logWdg.addOutput("%s %s\n" % (self.timeStamp(), msg))

    def setTitle(self, actorsToDisplay="", actorsToNotDisplay=""):
        if actorsToDisplay or actorsToNotDisplay:
            if actorsToNotDisplay:
                actorsToNotDisplay = "!" + actorsToNotDisplay.replace("|", " ").replace(" ", " !")

                if actorsToDisplay:
                    actorsToDisplay += " " + actorsToNotDisplay
                else:
                    actorsToDisplay = actorsToNotDisplay

            actorsToDisplay = "    Actors: [%s]" % actorsToDisplay.replace("|", " ")

        self.master.title("hubclient: %s%s" % (self.cmdrName, actorsToDisplay))


if __name__ == "__main__":
    if len(sys.argv) not in (1,3):
        print("Usage: hubclient addr [port]")
        sys.exit(1)
    
    addr = sys.argv[1] if len(sys.argv) > 1 else "localhost"
    port = sys.argv[2] if len(sys.argv) > 2 else 6093
    cmdrName = sys.argv[3] if len(sys.argv) > 3 else pwd.getpwuid(os.getuid()).pw_name
    
    root = tkinter.Tk()
    root.geometry("1000x500")
    client = TCPClient(root, addr, port, cmdrName=cmdrName)
    client.setTitle()

    client.pack(side="top", expand=True, fill="both")

    root.mainloop()
