import random
import mx
from mx import matrix

#=================================================================
#=================================================================
#=================================================================
def simule(self):
		#==============QUANTIFICATION===============================
		sum_residential = len(self.sum["residential"]) ; 
		if not sum_residential: sum_residential = 1
		sum_commercial = len(self.sum["commercial"]) ; 
		if not sum_commercial: sum_commercial = 1
		sum_industrial = len(self.sum["industrial"]) ; 
		if not sum_industrial: sum_industrial = 1
		sum_road = len(self.sum["road"]) ; 
		if not sum_road: sum_road = 1
		sum_rail = len(self.sum["rail"]) ; 
		if not sum_rail: sum_rail = 1
		sum_walk = len(self.sum["walk"]) ; 
		if not sum_walk: sum_walk = 1
		housing = 0.0 #sum of residential density
		revenue = 0.0 #sum of residential value
		consumation = 0.0 #sum of commercial density
		market = 0.0 #sum of commercial value
		production = 0.0 #sum of industrual density
		profit = 0.0 #sum of industrial value
		economy = 0.0 #sum of commercial & industrial value
		employment = 0.0 #sum of commercial & industrial density
		#=================NEIGHBORHOOD=====================================				#density increase if housing is low against population
		for tile in self.matrix.mx.values():
			tile.proceed()
			#============================
			tmp_around = tile.get_around()
			tile.stats["polution"] = self.stats["polution"] * 0.200 / sum_industrial
			tile.stats["crime"] = self.stats["crime"] * 0.200 / sum_residential
			tile.stats["trafic"] = self.stats["trafic"] * 0.200 / sum_road
			#residential
			if tile.typ == "residential":
				tile.stats["density"] = ((self.stats["population"] / sum_residential))%0.99
				tile.stats["value"] = (employment / sum_residential) * (1.0 - tile.stats["polution"])
				for neib in tmp_around:
					neib.stats["crime"] += (1.0 - tile.stats["value"])*0.200
				self.stats["crime"] += ((1.0 - tile.stats["value"]) / sum_residential)*0.200
				housing += tile.stats["density"]
				revenue += tile.stats["value"]
				economy += revenue
			#commercial
			elif tile.typ == "commercial":
				tile.stats["density"] = (housing / sum_commercial) % 0.99
				tile.stats["value"] = (revenue / sum_commercial) * (1.0 - tile.stats["crime"])
				for neib in tmp_around:
					neib.stats["trafic"] += tile.stats["density"]*0.200
				self.stats["trafic"] += (tile.stats["density"] / sum_commercial)*0.200
				consumation += tile.stats["density"]
				market += tile.stats["value"]
				employment += consumation
				economy += market
			#industrial
			elif tile.typ == "industrial":
				#density mean stock market stock value high then hi industrial need
				tile.stats["density"] = (self.stats["I"] * economy / sum_industrial) %0.99
				#value is the profit for a given production, if cosumation is high
				tile.stats["value"] = (self.stats["market"] / sum_industrial ) * (1.0 - tile.stats["trafic"])
				for neib in tmp_around:
					neib.stats["polution"] += tile.stats["density"]*0.200
				self.stats["polution"] += (tile.stats["density"] / sum_industrial)*0.200
				production += tile.stats["density"]
				profit += tile.stats["value"]
				employment += production
			#transport
			elif tile.typ == "road":
				for neib in tmp_around:
					neib.stats["polution"] += 0.2 * tile.stats["trafic"]
					#trafic principaly reducte productivity , people stuck in trafic have less time to work
					#but road presence increase productivity
					if neib.typ == "industrial" or neib.typ == "commercial":
						neib.stats["value"] += (1.0 - tile.stats["trafic"]) * 0.100
					
			elif tile.typ == "rail":
				pass
				#increase road trafic if crossing
				pass
			elif tile.typ == "walk":
				pass
			elif tile.typ == "tree":
				pass
			elif tile.typ == "water":
				pass
		#=============POPULATION======================
		employment = production + consumation
		economy = market + profit
		#many thing can inflict emmigration
		#is there space for new comer (residential density) sum of 1-density
		#is there jobs for all those peeps (employment) employment - current_population
		space_left = (sum_residential - housing)
		jobs_left = (employment - self.stats["population"])
		potential_emmigration = (space_left + jobs_left) /2
		self.stats["R"] = (jobs_left / (sum_industrial+sum_commercial)) - (space_left  / sum_residential)
		self.stats["population"] += random.random() * potential_emmigration
		#thing that influence economy
		#principaly , commerce demmand is influenced by people ability to buy
		potential_consumation = (revenue-consumation)	#how much people can buy more
		potential_grow = sum_commercial - consumation	#how much current commerce can grow
		self.stats["C"] = potential_consumation - potential_grow
		#thing that influence industrie
		#industrialisation lead to exportation so world economy is taken consideration
		#local commerce sell goods made in industry , so local economy is considered
		stock_value = ((market*consumation)+random.random())/2	#current stock value local and global
		potential_grow = sum_industrial - production	#current industrial facility can expand
		self.stats["I"] = stock_value - potential_grow


#=================================================================
#=================================================================
#=================================================================

class tile(object):
	def __init__(self,x,y,city):
		self.x, self.y, self.mx = x, y, city.matrix
		self.city = city
		self.devloped = False
		self.tin = None
		self.stats = {
		"polution":0.0,"crime":0.0,"trafic":0.0
		}

	def get_around(self):
		l = []
		for xy in self.mx.around(self.x,self.y):
			if xy:
				l.append(self.mx.at(xy))
		return l

	def update(self):
		pass
	
	def proceed(self):
		pass

class transport(tile):
	def __init__(self,x,y,city):
		tile.__init__(self,x,y,city)
		
	def update(self):
		name = self.typ
		if name == "road" and self.stats["trafic"] > 0.400:
			nname = self.trafic
			if self.trafic == "trafic0":
				self.trafic = "trafic1"
			else:
				self.trafic = "trafic0"
		else:
			nname = name
		(up,down,left,right) = self.mx.neighbor(self.x,self.y)
		if up:		up = self.mx.at(up).typ
		else:	up = "n/a"
		if down:	down = self.mx.at(down).typ
		else:	down = "n/a"
		if left :	left = self.mx.at(left).typ
		else:	left = "n/a"
		if right:	right = self.mx.at(right).typ
		else:	right = "n/a"
		if up=="road" and down=="road" and left=="walkway" and right=="walkway":
			return "vertical_road_with_walkway"
		elif up=="walkway" and down=="walkway" and left=="road" and right=="road":
			return "horizontal_road_with_walkway"
		elif up=="rail" and down=="rail" and left=="road" and right=="road":
			return "vertical_rail_with_road"
		elif up=="road" and down=="road" and left=="rail" and right=="rail":
			return "horizontal_rail_with_road"
		elif up=="rail" and down=="rail" and left=="walkway" and right=="walkway":
			return "horizontal_walkway_with_rail"
		elif up=="walkway" and down=="walkway" and left=="rail" and right=="rail":
			return "vertical_walkway_with_rail"
		elif up=="water" and down=="water" and left=="road" and right=="road":
			return "vertical_water_with_road"
		elif up=="water" and down=="water" and left=="rail" and right=="rail":
			return "vertical_water_with_rail"
		elif up=="water" and down=="water" and left=="walkway" and right=="walkway":
			return "vertical_water_with_walkway"
		elif up=="road" and down=="road" and left=="water" and right=="water":
			return "horizontal_water_with_road"
		elif up=="rail" and down=="rail" and left=="water" and right=="water":
			return "horizontal_water_with_rail"
		elif up=="walkway" and down=="walkway" and left=="water" and right=="water":
			return "horizontal_water_with_walkway"	
		elif up!=name and down!=name and (left==name or right==name):
			return "horizontal_"+nname
		elif (up==name or down==name) and left!=name and right!=name:
			return "vertical_"+nname
		elif up==name and down!=name and left!=name and right==name:
			return "upright_"+nname
		elif up==name and down!=name and left==name and right!=name:
			return "upleft_"+nname
		elif up!=name and down==name and left!=name and right==name:
			return "downright_"+nname
		elif up!=name and down==name and left==name and right!=name:
			return "downleft_"+nname
		else:	return "cross_"+nname

class building(tile):
	def __init__(self,x,y,city):
		tile.__init__(self,x,y,city)
		self.stats["value"] = 0.0
		self.stats["density"] = 0.0

	def proceed(self):
		tile.proceed(self)

#=================================================================
#=================================================================
#=================================================================

#-----------------------Nature

class grass(tile):
	def __init__(self,x,y,city):
		self.typ = "grass"
		magic = random.randint(0,30)
		if magic < 4:
			self.name = "grass" + str(magic)
		else:
			self.name = "none"
		tile.__init__(self,x,y,city)

class tree(tile):
	def __init__(self,x,y,city,name=None):
		self.typ = "tree"
		if name:
			self.name = name
		else:
			self.name = random.choice(["oak","tree0","tree1","boreal0"])
		tile.__init__(self,x,y,city)
	
class water(transport):
	def __init__(self,x,y,city):
		self.typ = "water"
		self.name = "horizontal_water"
		transport.__init__(self,x,y,city)
		
	def update(self):
		self.name = transport.update(self)

#---------------------transport

class road(transport):
	def __init__(self,x,y,city):
		self.typ = "road"
		self.name = "cross_road"
		self.trafic = "trafic0"
		transport.__init__(self,x,y,city)
		#self.stats["trafic"] = 0
		
	def update(self):
		self.name = transport.update(self)


class rail(transport):
	def __init__(self,x,y,city):
		self.typ = "rail"
		self.name = "cross_rail"
		transport.__init__(self,x,y,city)
		
	def update(self):
		self.name = transport.update(self)


class walkway(transport):
	def __init__(self,x,y,city):
		self.typ = "walkway"
		self.name = "cross_walkway"
		transport.__init__(self,x,y,city)
		
	def update(self):
		self.name = transport.update(self)

#-----------------------building

class residential(building):
	def __init__(self,x,y,city):
		self.typ = "residential"
		self.name = "residential"
		building.__init__(self,x,y,city)
	
	def proceed(self):
		building.proceed(self)
		#===============
		if (self.name == "residential" and self.stats["density"] != 0.0) or ("condo" in self.name and self.stats["density"] < 0.5) or ("house" in self.name and self.stats["density"] >= 0.5):
			if self.stats["density"] > 0.5:
				self.name = "condo"+ str(random.randint(0,8))
			else:
				self.name = "house"+ str(random.randint(0,8))

class commercial(building):
	def __init__(self,x,y,city):
		self.typ = "commercial"
		self.name = "commercial"
		building.__init__(self,x,y,city)
	
	def proceed(self):
		building.proceed(self)
		#============
		if (self.name == "commercial" and self.stats["density"] != 0.0) or ("office" in self.name and self.stats["density"] < 0.5) or ("commerce" in self.name and self.stats["density"] >= 0.5):
			if self.stats["density"] > 0.5:
				self.name = "office"+ str(random.randint(0,8))
			else:
				self.name = "commerce"+ str(random.randint(0,8))

class industrial(building):
	def __init__(self,x,y,city):
		self.typ = "industrial"
		self.name = "industrial"
		building.__init__(self,x,y,city)
	
	def proceed(self):
		building.proceed(self)
		#===============
		if (self.name == "industrial" and self.stats["density"] != 0.0)  or ("shop" in self.name and self.stats["density"] < 0.5) or ("farm" in self.name and self.stats["density"] >= 0.5):
			if self.stats["density"] > 0.3:
				self.name = "shop"+ str(random.randint(0,8))
			else:
				self.name = "farm"+ str(random.randint(0,8))

#=================================================================
#=================================================================
#=================================================================
#=================================================================
#=================================================================
#=================================================================



#=================================================================
#=================================================================
#=================================================================

def trip_cost(tile):
	if tile.typ == "road":
		if tile.stats["trafic"] < 10:
			tile.stats["trafic"] +=1
			return 1
		else:
			return None
	return 10

class city(object):
	def __init__(self,name):
		self.year = 0
		self.cash = 0
		self.pop = 0
		self.name = name
		self.R = 0	#residential
		self.C = 0	#commercial
		self.I = 0	#industrial
		self.matrix = matrix(24,24)
		for (x,y) in self.matrix.all():
			self.matrix.at(x,y,grass(x,y,self))
		self.action = {	
		"residential":residential,"commercial":commercial,\
		"industrial":industrial,"construction":grass,\
		"tree":tree,"water":water,"road":road,"rail":rail,"walk":walkway
		}
		self.stats = {
		"polution":0,"crime":0,"trafic":0,\
		#"birthrate":0,"productivity":0,"economy":0,"R_income":0,\
		"employment":0,"housing":0,\
		"R":0,"C":0,"I":0,\
		"stock":0,"market":0,\
		"population":0,"money":0
		}
		self.sum = {
		"residential":[],"commercial":[],"industrial":[],"road":[],"rail":[],"walk":[],"tree":[],"water":[]\
		}
		self.sum_R = 0
		self.sum_I = 0
		self.sum_C = 0
	
	def build(self,x,y,name):
		if name == "construction":
			tmp = self.matrix.at(x,y)
			if tmp.typ in self.sum:
				if (x,y) in self.sum[tmp.typ]:
					self.sum[tmp.typ].remove((x,y))
		if name in self.action:
			self.matrix.at(x,y, self.action[name](x,y,self))
			if name in self.sum:
				self.sum[name].append((x,y))
	
	def proceed(self):
		simule(self)
