#!/usr/bin/python3
from math import *
import random
import string
import sys
import os

from common import *
from longrandom import LongRandom
from worddict import words

print("Content-Type: text/html")
print()

qs = os.environ.get('QUERY_STRING', None)
if not qs:
	minlen = 1
	maxlen = 8
	numlen = 2
	wordcount = 3
	extra_symbols = ''
	randcaps = 'first'
else:
	form = cgi.FieldStorage()
	wordcount = form_get(form, 'wordcount', 3, int)
	minlen = form_get(form, 'minlen', 2, int)
	maxlen = form_get(form, 'maxlen', 8, int)
	numlen = form_get(form, 'numlen', 2, int)
	randcaps = form_get(form, 'randcaps', 'first', str)

dumpfile('header.html', {'type':'Passphrase'})
dict = EvalDict(vars())
here = os.path.dirname(__file__)
form_path = os.path.join(here, 'ppform.html')
with open(form_path, encoding="utf-8") as f:
    sys.stdout.write(f.read() % dict)

usewords = [ ]
totalen = 0
for i in range(minlen, maxlen+1):
	totalen += len(words[i]) * i
	usewords.extend(words[i])

log_2 = log(2)
wordbits = log(len(usewords)) / log_2
medlen = len(usewords[len(usewords)//2])
avglen = totalen / len(usewords)
if randcaps == 'first':
	capbits = 1
	capmult = 2
elif randcaps == 'one':
	# Use estimate based on average word length
	capbits = log(avglen+1) / log_2
	capmult = avglen+1
elif randcaps == 'all':
	# One bit per average word length
	capbits = avglen
	capmult = 2**avglen
else:
	capbits = 0
	capmult = 1
numbits = log(10) * numlen / log_2
numfmt = '{{:0{}}}'.format(numlen)
passbits = (wordbits + capbits) * wordcount + numbits * ((wordcount - 1) or 1)

table_start()
row('Word count', commafy(len(usewords)))
row('Average word length', '%.2f' % avglen)
row('Bits per word', '%.2f' % wordbits)
row('Bits per number', '%.2f' % numbits)
row('Bits for capitalization', '%.2f' % (capbits * wordcount))
row('Effective passphrase bits', int(passbits))
row('Total possible combinations',
	commafy(len(usewords)**wordcount * (10**numlen)**((wordcount-1) or 1) * capmult**wordcount))
table_end()

randval = LongRandom()

table_start()
print("<tr><th>Passphrase</th></tr>")
for i in range(10):
	passphrase = ''
	for j in range(wordcount):
		word = usewords[randval.get(len(usewords))]
		if randcaps == 'first':
			if randval.get(2):
				word = word[0].upper() + word[1:]
		elif randcaps == 'one':
			k = randval.get(len(word)+1)
			if k < len(word):
				word = word[:k] + word[k].upper() + word[k+1:]
		elif randcaps == 'all':
			word = ''.join([ randval.get(2) and ch.upper() or ch.lower()
							 for ch in word ])
		passphrase += word
		if numlen > 0 and (j < wordcount-1 or wordcount == 1):
			passphrase += numfmt.format(randval.get(10 ** numlen))

	print("<tr><td><tt>%s</tt></td></tr>" % escape(passphrase))

table_end()
dumpfile('footer.html')
