#!/usr/bin/env python
# twistedwebcalc3.py -- A Twisted.Web web calculator using a FORM.

from twisted.web import server, resource
from twisted.internet import reactor

class WebCalcForm(resource.Resource):
    isLeaf = True

    def render_GET(self, request):
        # 1. Fetch arguments from URL or POST arguments using request
        # (which is also a twisted.web.http.Request object)
        op = request.args.get('op', None)
        arg1 = request.args.get('arg1', None)
        arg2 = request.args.get('arg2', None)

        # 2. If arguments ar missing, send input form
        if op is None or arg1 is None or arg2 is None:
            return self.create_form()

        # URL or POST arguments are always returned as a list
        # in case they occur mutiple times as in op=add&op=sub.
        op = op[0]
        arg1 = arg1[0]
        arg2 = arg2[0]

        # 3. Sanity checks and calculations
        if op not in ('add', 'sub', 'mul', 'div'):
            return "Invalid operator. Use 'add', 'sub', 'mul', or 'div'\r\n"

        result = 0.0
        try:
            numarg1 = float(arg1)
            numarg2 = float(arg2)
            if op == 'add': result = numarg1 + numarg2
            elif op == 'sub': result = numarg1 - numarg2
            elif op == 'mul': result = numarg1 * numarg2
            elif op == 'div':
                if numarg2 == 0: result = 'NaN'
                else:            result = numarg1 / numarg2
        except ValueError:
            result = "Invalid operand: use numerical values only\r\n"
        finally:
            return str(result) + "\r\n"

    def create_form(self):
        return '''
<form action='/' method='POST'>
  <input type="text" size="20" name="arg1" value="number 1" />
  <select name="op">
    <option>add</option>
    <option>sub</option>
    <option>mul</option>
    <option>div</option>
  </select>
  <input type="text" size="20" name="arg2" value="number 2" />
  <br />
  <input type="submit" value="Calculate" />
  <input type="reset" value="Clear fields" />
</form>
'''

if __name__ == '__main__':
    root = WebCalcForm()
    root.render_POST = root.render_GET
    
    site = server.Site(root)
    reactor.listenTCP(9090, site)
    reactor.run()
