# uuid=ed718cf7-968e-4e39-9053-3425f43b8fee
# version=1

if version\0 < 1:

    from channels import User, Channel, Thread, Message, dispatch_message_to_channel, format_message

    TOKEN   = file_lines('secrets/test.token')[0]   -- Place your telegram bot token in ./secrets/test.token with no spaces
    tg_poll = PrimaTelegramUpdates{TOKEN}
    tg_me   = PRIMOP{'Ftg_me'    , TOKEN}
    tg_send = PRIMOP{'Ftg_send'  , TOKEN}


    type TelegramUser in User:
        var tg_user

    type TelegramChannel in Channel:
        val tg_chat

    type TelegramMessage in Message:
        val tg_msg                  -- Map of orig telegram message

    (|
     | Remember these maps are actually database tables, so it's
     |   fine if they get huge.  And they live forever:
     |)
    tg_users       = [:]            -- Maps from telegram user.id to TelegramUser object.
    tg_channels    = [:]            -- Maps from telegram chat.id to TelegramChannel object.
    tg_messages    = [:]            -- Maps from telegram message.id to Message object.

    def get_TelegramChannel(tg_chat):
        if not (id = tg_chat.id)?:
            raise("Missing id")
        if not (chan = tg_channels[id])?:
            print("TELEGRAM: Creating new telegram channel for chat id {id}")
            chan = tg_channels[id] = TelegramChannel(tg_chat=tg_chat)
        return chan

    def new_TelegramUser(tg_user, chan):
        tg_users[tg_user.id] = user = TelegramUser(tg_user=tg_user, name=tg_user.first_name\tg_user.username, default_channel=chan)
        print("TELEGRAM: Created new user {user.name}:")
        pprint(user)
        return user

    def get_TelegramUser(tg_user, chan):
        if (user=tg_users[tg_user.id])?:
            return user
        return new_TelegramUser(tg_user, chan)

    def new_TelegramMessage(chan, tg_msg):
        m = TelegramMessage(when=tg_msg.date, text=tg_msg.text, from=get_TelegramUser(tg_msg.from, chan), tg_msg=tg_msg, channel=chan, in_reply_to=tg_messages[tg_msg.reply_to_message.message_id])
        tg_messages[tg_msg.message_id] = m
        return m

    def send_message_to_telegram_channel(chan, text):
        print("TELEGRAM: Sending to {chan}: {text}")
        tg_msg = tg_send(chan.tg_chat.id, text)
        return new_TelegramMessage(chan, tg_msg)

    tg_agent = new_TelegramUser(tg_me())
    tg_agent.name = "Agent"

    (|
     | At the moment, this spawns this forever-task in the global task pool,
     |  which allows the version=1 below to run and the module to exit.
     |
     | Eventually this (by default) will spawn at the module level, essentially
     |  keeping the module running forever or until we kill (cancel) the module,
     |  which would kill tasks like this (and ultimately allow GC to clean up
     |  the entire module if we drop all references to it).
     |
     | This gets tricky for updating modules: We need to make sure to run the
     |  newly imported version of the module using the same task pool, and then
     |  that code would have to selectively kill and restart (if applicable)
     |  old processes directly (or just leave them running if they are still
     |  viable).  In general how to handle in-progress goals (waiting tasks)
     |  during a significant module version upgrade is a sticky problem.  Some
     |  foresight in module design would probably help here; need to establish
     |  good patterns for this, but it feels very non-trivial atm.
     |
     | ALSO, at the moment this doesn't catch or handle exceptions at all,
     |  so will just die ungracefully and leave a dead module if anything
     |  goes wrong.  Generally true everywhere right now -- focus so far
     |  has been on exploring the approach when things are working; next
     |  comes handling the ways things might fail...
     |)
    spawn:
        print('About to call tg_poll() for the first time...')
        while (updates = tg_poll())?:
            for update in updates:
                print('TELEGRAM: Got an update')
                if (m = update.message)?:
                    chan = get_TelegramChannel(m.chat)
                    m    = new_TelegramMessage(chan, m)
                    print("TELEGRAM: {format_message(m)}")
                    dispatch_message_to_channel(m, chan)
                else:
                    print('TELEGRAM: WARNING: Unhandled telegram update:')
                    pprint(update)
                print('TELEGRAM: Waiting for next update...')

    version = 1