#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

from __future__ import print_function
import tornado.ioloop
import tornado.web
from tornado.gen import coroutine
from tornado.concurrent import Future
from proton import Message
from proton.handlers import MessagingHandler
from proton_tornado import Container

class Client(MessagingHandler):
    def __init__(self, host, address):
        super(Client, self).__init__()
        self.host = host
        self.address = address
        self.sent = []
        self.pending = []
        self.reply_address = None
        self.sender = None
        self.receiver = None

    def on_start(self, event):
        conn = event.container.connect(self.host)
        self.sender = event.container.create_sender(conn, self.address)
        self.receiver = event.container.create_receiver(conn, None, dynamic=True)

    def on_link_opened(self, event):
        if event.receiver == self.receiver:
            self.reply_address = event.link.remote_source.address
            self.do_request()

    def on_sendable(self, event):
        self.do_request()

    def on_message(self, event):
        if self.sent:
            request, future = self.sent.pop(0)
            print("%s => %s" % (request, event.message.body))
            future.set_result(event.message.body)
            self.do_request()

    def do_request(self):
        if self.pending and self.reply_address and self.sender.credit:
            request, future = self.pending.pop(0)
            self.sent.append((request, future))
            req = Message(reply_to=self.reply_address, body=request)
            self.sender.send(req)

    def request(self, body):
        future = Future()
        self.pending.append((body, future))
        self.do_request()
        self.container.touch()
        return future

class ExampleHandler(tornado.web.RequestHandler):
    def initialize(self, client):
        self.client = client

    def get(self):
        self._write_open()
        self._write_form()
        self._write_close()

    @coroutine
    def post(self):
        response = yield self.client.request(self.get_body_argument("message"))
        self.set_header("Content-Type", "text/html")
        self._write_open()
        self._write_form()
        self.write("Response: " + response)
        self._write_close()

    def _write_open(self):
        self.write('<html><body>')

    def _write_close(self):
        self.write('</body></html>')

    def _write_form(self):
        self.write('<form action="/client" method="POST">'
                   'Request: <input type="text" name="message">'
                   '<input type="submit" value="Submit">'
                   '</form>')


loop = tornado.ioloop.IOLoop.instance()
client = Client("localhost:5672", "examples")
client.container = Container(client, loop=loop)
client.container.initialise()
app = tornado.web.Application([tornado.web.url(r"/client", ExampleHandler, dict(client=client))])
app.listen(8888)
try:
    loop.start()
except KeyboardInterrupt:
    loop.stop()
