#!/usr/bin/python

# IIProvider.py
#       --copyright--                   Copyright 2007 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       September 5, 2005       bar
#       September 7, 2005       bar     cmd line @ files and params
#       November 18, 2007       bar     turn on doxygen
#       November 27, 2007       bar     insert boilerplate copyright
#       May 17, 2008            bar     email adr
#       August 29, 2008         bar     basestring instead of StringType because of unicode strings and others
#       May 27, 2012            bar     doxygen namespace
#       July 7, 2018            bar     pyflakes
#       --eodstamps--
##      \file
#       \namespace              tzpython.IIProvider
#
#
#       Be a an II provider.
#
#       Query and AuthQuery messages come in this form:
#
#           sid (Auth)Query provider_acceptmsgs_name::query_to_iiserver_first_field (fields...) query
#         or:
#           sid (Auth)Query               logon_name::query_to_iiserver_first_field (fields...) query
#
#           Providers logged in to the iiserver may send AuthQuery messages to the server.
#
#           The server puts a default "Unk-source" value in place of 'provider_acceptmsgs_name' if the querier has not set an AcceptMsgs name.
#
#       Querys to the server are sent in the form:
#
#
#
#

import  AmpClient
import  tgcmsg


class an_ii_provider :

    def __init__(me, host        = None,
                     port        = None,
                     user_name   = None,
                     password    = None,
                     name        = None,
                     regx        = None,
                     screen_info = False
                    ) :

        if  not host :  host    = "localhost"
        if  not port :  port    = 13460
        if  not name :  name    = "an_ii_provider"
        if  not regx :  regx    = "?"

        me.clt                  = AmpClient.an_amp_client(host, port, user_name, password)

        me.name                 = name
        me.regx                 = regx
        me.drop_when_able       = False
        me.accepting            = False
        me.accept_msgs_sid      = 0


        me.screen_info          = me.clt.screen_info   = screen_info

        me.q                    = []

        pass



    def get_query(me) :
        """
            Get the next query that the server has sent to us.
            Return None if there are no messages in our queue.
        """

        if  not len(me.q)   :   return(None)

        return(me.q.pop(0))


    def respond(me, q, r) :
        """
            Respond to a query.
        """

        if  isinstance(r, basestring) :
            r   =   r.strip()
            if  r : r += " "
            r   =   [ r ]

        r.insert(0, q[0])
        r.insert(1, "lst" + q[1])
        me.clt.send_msg(r)


    def send_msg(me, msg) :

        return(me.clt.send_msg(msg))


    def on_line(me) :
        """
            Are we on line with a server and accepting queries?
        """

        return(me.accepting and me.clt.on_line())



    def drop(me) :
        """
            Drop the connection - instantly.
        """

        if  me.screen_info  :                                                                                   print "Dropping IIProvider"

        me.accepting        =   False
        me.accept_msgs_sid  =   0
        me.q                =   []

        me.clt.drop()


    def shutdown(me) :
        """
            Disconnect from the server in a controlled manner.
            That is, stop accepting queries and drop the connection when we get the AcceptMsgs acknowledgment.
        """

        me.name = None              # signal to the ack-handling logic that we're shutting down

        if  (not me.drop_when_able) and me.clt.on_line() :
            me.accept_msgs_sid = me.clt.sid_send("AcceptMsgs")
        elif     me.drop_when_able  and (len(me.q) == 0) :
            me.drop()

        pass




    def do_it(me) :
        """
            Do whatever needs be done - get queries.
        """

        lo  = me.clt.logged_on

        me.clt.do_it()


        if  me.clt.logged_on :

            if  not lo :
                me.drop_when_able         = False

                while   me.clt.get_msg() != None :
                    pass

                if  (not me.regx) or (not me.name):
                    me.accepting    = True
                else :
                    me.accept_msgs_sid = me.clt.sid_send("AcceptMsgs '" + me.name + '" "' + me.regx + '"')
                    if  me.screen_info  :                                                                       print "Logged on"
                pass

            msg = me.clt.get_msg()
            if  msg :
                sid = msg[0]
                v   = msg[1].upper()

                if  (v == "YESACCEPTMSGS") or (v == "YESAUTHACCEPTMSGS") :
                    if  sid == str(me.accept_msgs_sid) :
                        me.accept_msgs_sid  = 0
                        if  me.name != None :
                            me.accepting        = True
                            if  me.screen_info  :                                                               print "Accepting"
                        else :
                            me.drop_when_able   = True
                            if  len(me.q) == 0 :
                                me.drop()
                            pass
                        pass
                    pass

                elif (v == "QUERY") or (v == "AUTHQUERY") :
                    me.q.append(msg)

                else :
                    if  me.screen_info :                                                                        print "Unhandled IIProvider msg:", msg
                    pass

                pass

            pass


        return(len(me.q) > 0)





#
#
#   Test code.
#
#
if __name__ == '__main__' :
    import  sys

    import  TZCommandLineAtFile
    import  tzlib


    del(sys.argv[0])

    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)

    user_name       = None
    password        = None
    provider_name   = "IIProvider"
    regx            = "?"
    server          = "localhost"
    port            = 13460

    print sys.argv

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--user", "-u" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        user_name   = sys.argv.pop(oi)
        password    = sys.argv.pop(oi)
        print "user", user_name, "pw", password

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--name", "-n" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        provider_name   = sys.argv.pop(oi)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--regx", "-r" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        regx   = sys.argv.pop(oi)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--server", "-s" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        server  = sys.argv.pop(oi)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--port", "-p" ] )
        if  oi < 0 :    break
        del sys.argv[oi]
        port  = int(sys.argv.pop(oi))



    if  len(sys.argv) > 0 :
        print   "Too many command line params!", sys.argv
        sys.exit(101)


    clt             = an_ii_provider(host        = server,
                                     port        = port,
                                     user_name   = user_name,
                                     password    = password,
                                     name        = provider_name,
                                     regx        = regx,
                                     screen_info = True
                                    )

    while True :
        if  clt.do_it() :
            while True :
                m      = clt.get_query()
                if  m == None : break

                print tgcmsg.tgc_msg(m)

                if  m[len(m) - 1].lower() == "stop" :
                    clt.respond(m, "stopping")
                    clt.shutdown()
                    print "first shutdown called"
                else :
                    clt.respond(m, "ok dokee")
            pass
        pass

        if  clt.drop_when_able :
            print "Trying to really shutdown"
            clt.shutdown()
            if  not clt.on_line() :
                break
            pass
        pass



__all__ = [
            'an_ii_provider',
          ]




#
#
#
# eof
