#!/usr/bin/python
import random
import optparse
import os
import bisect
import dice
import re

parser = optparse.OptionParser('%prog [options] [times to roll] <random table>', epilog='Example: python random d4 --locale West/Foothills Encounters')
parser.add_option('-l', '--locale')
(options, args) = parser.parse_args()

#load the table into the appropriate class
def tableFactory(name):
	filename = name + '.txt'
	filepath = filename
	if options.locale:
		localepath = os.path.join(options.locale, filename)
		if os.path.exists(localepath):
			filepath = localepath

	if not os.path.exists(filepath):
		return None

	items = open(filepath).read().decode('utf-8')
	if "\t" in items:
		table = PercentTable(items)
	else:
		table = SimpleTable(items)
	return table

#a table is a list of items that we choose randomly from
class Table(object):
	#print some random items from the table
	def choose(self, count):
		if type(count) is not int:
			if count.isdigit():
				count = int(count)
			else:
				count = dice.roll(count + 't')
				if count == 1:
					time = 'time:'
				else:
					time = 'times:'

				print 'Rolling', count, time
				print

		maximumLength = len(unicode(count))
		formatString = '%' + unicode(maximumLength) + 'i. %s'
		for counter in range(count):
			if count > 1:
				print formatString % (counter+1, self.choice())
			else:
				print self.choice()

#a simple table is a list of items with equal probability
class SimpleTable(Table):
	#load the list of items and save it
	def __init__(self, items):
		self.items = items.splitlines()

	#choose a random item from the table
	def choice(self):
		return random.choice(self.items)

class PercentTable(Table):
	#load the list of items and save it
	def __init__(self, items):
		self.items = []
		for line in items.splitlines():
			#generate the range, all we need is the high number
			(dieRange, item) = line.split("\t")
			if '-' in dieRange:
				(lowDie, highDie) = dieRange.split('-')
			else:
				highDie = dieRange
			highDie = int(highDie)

			#00 is often used in place of 100 in wandering monster tables
			if highDie == 0:
				highDie = 100

			#generate the number appearing
			appearing = ''
			appearance = ''
			if item.endswith(')'):
				dieStart = item.rindex('(')
				appearing = item[dieStart:]
				appearing = appearing.strip('()')
				if ' ' in appearing:
					appearing, appearance = appearing.split(' ', 1)
					appearance = ' ' + appearance
				if 'd' in appearing and '+' not in appearing and '-' not in appearing:
					appearing = appearing + 't'
				item = item[:dieStart]
				item = item.strip()

			self.items.append((highDie, item, appearing, appearance))

	#choose a random item from the table
	def choice(self):
		#generate a number from 1 to 100
		d100 = random.randrange(100)+1

		#find the corresponding line
		line = bisect.bisect_right(self.items, (d100,))
		(high, item, appearing, appearance) = self.items[line]
		numberAppearing = ''
		if appearing == '':
			#is this a reference to another table?
			subtable = tableFactory(item)
			if subtable:
				return subtable.choice()
		else:
			subtable = tableFactory(appearing)
			if subtable:
				return item + ' ' + subtable.choice()

			numberAppearing = dice.roll(appearing)
			numberAppearing = ' (' + unicode(numberAppearing) + appearance + ')'

		item = item + numberAppearing
		return item

count = 1
while args:
	firstArgument = args.pop(0)

	#if the first argument is a number, it's the number of random items we want
	#otherwise, it is the table and we want one item from it
	if re.match(r'[0-9]*d?[1-9][0-9]*$', firstArgument):
		count = firstArgument
		tableName = args.pop(0)
	else:
		tableName = firstArgument

	table = tableFactory(tableName)
	if table:
		table.choose(count)
	else:
		print 'Cannot find table', tableName
	print
