class StoreGenerator(object):
	def __init__(self, zipcode_pop):
		self.zipcode_pop = zipcode_pop
		pdf = ZipcodePDF(zipcode_pop)
		generator = ZipcodeGenerator(zipcode_pop)
		self.mcmc = MonteCarloGenerator(generator, pdf)

	def generate_n(self, n):
		zipcodes = self.generate_zipcodes(n)
		stores = self.create_stores(zipcodes)
		return stores

	def generate_zipcodes(self, n):
		zipcodes = []
		for i in xrange(n):
			zipcode = self.mcmc.generate()
			zipcodes.append(zipcode)
		return zipcodes


	def create_stores(self, zipcodes):
		ids = np.arange(len(zipcodes))
		populations = self.zipcode_pop.loc[zipcodes]
		total_pop = np.float64(populations.sum(axis=0))
		pop_density = populations.divide(total_pop)
		return pd.DataFrame(data={"id" : ids, "zipcode" : zipcodes, "pop_density" : pop_density}, index=zipcodes)
class CustomerGenerator(object):
	def __init__(self, stores):
		self.stores = stores
		gen = CustomerInstanceGenerator(stores)
		pdf = CustomerPDF(stores)
		self.mcmc = MonteCarloGenerator(gen, pdf)

	def generate_n(self, n):
		prototypes = self.generate_customers(n)
		finalized = self.finalize_customers(prototypes)
		return finalized

	def generate_customers(self, n):
		customers = []
		for i in xrange(n):
			customer = self.mcmc.generate()
			customers.append(customer)
		return customers

	def finalize_customers(self, customers):
		zipcodes = []
		pets = []
		names = []
		purchase_values = []
		value_total = 0.0
		ids = np.arange(len(customers))
		for c in customers:
			zipcodes.append(c["zipcode"])
			pets.append(c["pet_type"])
			names.append(c["name"])
			purchase_values.append(c["purchase_value"])
			value_total += c["purchase_value"]
		purchase_pdf = [value / value_total for value in purchase_values]
		return pd.DataFrame(data={"id" : ids, "name" : names, "zipcode" : zipcodes, "pet_type" : pets, "purchase_pdf" : purchase_pdf}, index=ids)
class StoreSampler(object):
	def __init__(self, stores):
		pdf = StoreSamplerPDF(stores)
		gen = StoreSamplerGenerator(stores)
		self.mcmc = MonteCarloGenerator(gen, pdf)

	def sample(self):
		return self.mcmc.generate()
class CustomerGenerator(object):
    def __init__(self, stores):
        self.stores = stores
        gen = CustomerInstanceGenerator(stores)
        pdf = CustomerPDF(stores)
        self.mcmc = MonteCarloGenerator(gen, pdf)

    def generate_n(self, n):
        prototypes = self.generate_customers(n)
        finalized = self.finalize_customers(prototypes)
        return finalized

    def generate_customers(self, n):
        customers = []
        for i in xrange(n):
            customer = self.mcmc.generate()
            customers.append(customer)
        return customers

    def finalize_customers(self, customers):
        zipcodes = []
        pets = []
        names = []
        purchase_values = []
        value_total = 0.0
        ids = np.arange(len(customers))
        for c in customers:
            zipcodes.append(c["zipcode"])
            pets.append(c["pet_type"])
            names.append(c["name"])
            purchase_values.append(c["purchase_value"])
            value_total += c["purchase_value"]
        purchase_pdf = [value / value_total for value in purchase_values]
        return pd.DataFrame(data={
            "id": ids,
            "name": names,
            "zipcode": zipcodes,
            "pet_type": pets,
            "purchase_pdf": purchase_pdf
        },
                            index=ids)