#########################################################################
#Titre: Creer_carte.py
#Depuis:18/01/2014
#A participé: MARCAULT Vivien
#
#Description: Programme permettant de créer une carte Tower defence
#et de l'enregistrer
#
#Dernière modification: 03/02/2014 Vivien
#########################################################################
#----------------------------------------------------------------------
#Commentaires
#----------------------------------------------------------------------
#Commentaires du code à venir
#seulement récupérer 40 chemins sur les chemins calculés

#----------------------------------------------------------------------
#Initialisation
#----------------------------------------------------------------------
from tkinter.filedialog import *
from pickle import *
from tkinter import *
from PIL import ImageGrab
fen=Tk()
from entite import Vague
from info import ICase,CaseVide
fen.resizable(width=False,height=False)
fen.title ("Tower Defence - Editeur de Carte")
fen.iconbitmap ("img/Icone.ico")

#----------------------------------------------------------------------
#Création des variables
#----------------------------------------------------------------------
#variable de sélection de la case à poser
selection=StringVar()
selection.set(0)

pause =0
dir=0 #direction vers le fichier

chateau=0#case du chateau par défault il n'y en a pas
LCase=[]
LChemin=[]
LVague=[]
Vie=30
Argent=100


Sol={}

Mob1=PhotoImage(file="img/Mob/Mob1/Mob1.gif")
Mob2=PhotoImage(file="img/Mob/Mob2/Mob2.gif")
Mob3=PhotoImage(file="img/Mob/Mob3/Mob3.gif")
Mob4=PhotoImage(file="img/Mob/Mob4/Mob4.gif")

ICase2=	{0:PhotoImage(file="img/terrain/herbe.gif")}
for i in range(1,12):
	ICase2[i]=PhotoImage(file="img/Autre/Bouton/route{}.gif".format(i))

#----------------------------------------------------------------------
#Définition des fonctions et de la classe Case
#----------------------------------------------------------------------

class Case:
	
	def __init__ (self,x,y,t,fen,cadre,selection,chateau,LCase):
		#x et y en coordonnées dee cases pas de px
		self.x=x
		self.y=y
		
		self.t=t
		self.sol=cadre.create_image(x*29-15, y*29-15, image=ICase[t])
		self.vide=cadre.create_image(x*29-15, y*29-15, image=CaseVide,tag=self.sol)
		cadre.tag_raise(self.vide,ALL)
		
		cadre.tag_bind(self.vide, "<Button-1>", lambda event: self.change(cadre,selection,LCase))
		cadre.tag_bind(self.vide, "<Button-2>", lambda event: self.identite())
	
	def change (self,cadre,selection,LCase):
		global chateau
		
		if  selection.get()=="chateau":
			try:chateau.change(cadre,StringVar(value='0'),LCase)
			except:pass
			chateau=self
			cadre.itemconfig(self.sol,image=ICase[selection.get()])
			self.t=selection.get()
			cadre.tag_raise(self.sol,ALL)
			for case in LCase:
				cadre.tag_raise(case.vide,ALL)
			
		else:
			if chateau==self: chateau=0
			cadre.itemconfig(self.sol,image=ICase[int(selection.get())])
			self.t=int(selection.get())
			
			try: cadre.tag_lower(self.sol,chateau.sol)
			except:pass
			
		cadre.tag_raise(self.vide,ALL)
	
	def identite (self):
		selection.set(self.t)
		
#Fonstions d'ouverture et d'enregistrement de carte
def Enregistrer_sous():
	global dir

	dir=asksaveasfilename(title="Sauvegarder la carte",initialdir="Save/Cartes",filetypes=[("Carte Tower Defence","*.twc")])
	if dir[len(dir)-4:]!=".twc": dir= dir+".twc"
	Enregistrer()
	
def Enregistrer():
	"""fonction permettant d'enregistrer la map"""
	global dir,pause

	pause=1

	for i in range(len(LVague)):
		LVague[i].rang=i
	
	carte={"Sol":Sol,"Chemin":LChemin,"Vague":LVague,"Vie":Vie,"Argent":Argent,"Version":"Beta"}
	if dir==0 or "":
		dir=asksaveasfilename(title="Sauvegarder la carte",initialdir="Save/Cartes",filetypes=[("Carte Tower Defence","*.twc")] )
		if dir[len(dir)-4:]!=".twc": dir= dir+".twc"
	with open(dir,'wb')as fichier:
		mon_pickler=Pickler(fichier)
		mon_pickler.dump(carte)
	Relancer()
	rec(dir)

def rec(dir):
	fen.geometry( "790x640" )
	fen.update_idletasks()
	taille=fen.geometry().split("+")
	x=int(taille[1])+5
	y=int(taille[2])+100
	image=ImageGrab.grab((x,y,x+640,y+580))
	dir=dir.split(".twc")
	image.save('{}.bmp'.format(dir[0]))	
	
def Ouvrir():
	global LChemin,LVague,dir,Vie,Argent

	dir=askopenfilename(title="Ouvrir la carte",initialdir="Save/Cartes",filetypes=[("Carte Tower Defence","*.twc")])
	with open(dir,'rb')as fichier:
		mon_pickler=Unpickler(fichier)
		carte=mon_pickler.load()
	LChemin = carte["Chemin"]
	LVague = carte["Vague"]
	Vie=carte["Vie"]
	Argent = carte["Argent"]
	for case in LCase:
		v=StringVar()
		v.set(carte["Sol"][(case.x,case.y)])
		case.change(cadre,v,LCase)
		
	
#Fonctions de dynamique du programme
def Actualisation(MLChemin=[],MLVague=[],MVSelect=-1,MCSelect=-1):
	#M= mémoire pour comparer entre deux boucles
	#LChemin => MLChemin
	
	#Permet l'actualisation de la liste de chemins
	if not pause:
		if LChemin != MLChemin:
			BChemin.delete(0,END)
			for i,chemin in enumerate(LChemin):
				BChemin.insert(END, "Chemin {}".format(i))
			MLChemin=LChemin

		if BChemin.curselection()!=():
			select=int(BChemin.curselection()[0])
			if select!=MCSelect:
				cadre.delete('ligne'+str(MCSelect))
				TracerChemin(select)
				MCSelect=select
		else:
			try:cadre.delete('ligne'+str(MCSelect))
			except:pass
		
			
		if LVague != MLVague:
			BVague.delete(0,END)
			for i,vague in enumerate(LVague):
				BVague.insert(END, vague.nom)
			MLVague=LVague.copy()
		
		if BVague.curselection()!=():
			select=int(BVague.curselection()[0])
			if select!=MVSelect:
				ConfigVague(select)
				MVSelect=select
		CCDepart()
	
	fen.after(100,Actualisation,MLChemin,MLVague,MVSelect,MCSelect)
	
def TracerChemin (select):
	Chemin = LChemin[select]
	for i,(x,y) in enumerate(Chemin):
		if i != len(Chemin)-1:
			cadre.create_line(x,y,Chemin[i+1][0],Chemin[i+1][1],width=3,tag='ligne'+str(select))

def CreerVague():
	LVague.append(Vague())
	
def ConfigVague(i):
	global CVague
	CVague.grid_forget()
	CVague=Frame(F2,width=131,height=204,bg='white',bd=2,relief=GROOVE)
	CVague.pack_propagate(False)
	CVague.grid(row=1,column=0,pady=2)
	vague=LVague[i]
	
	nom =StringVar()
	nom.set(vague.nom)
	
	duree=IntVar()
	duree.set(vague.duree)
	
	NbMob1=IntVar()
	NbMob1.set(vague.Mob1)
	LvlMob1=IntVar()
	LvlMob1.set(vague.lvlMob1)
	
	NbMob2=IntVar()
	NbMob2.set(vague.Mob2)
	LvlMob2=IntVar()
	LvlMob2.set(vague.lvlMob2)
	
	NbMob3=IntVar()
	NbMob3.set(vague.Mob3)
	LvlMob3=IntVar()
	LvlMob3.set(vague.lvlMob3)
	
	NbMob4=IntVar()
	NbMob4.set(vague.Mob4)
	LvlMob4=IntVar()
	LvlMob4.set(vague.lvlMob4)
	
	Entry(CVague,width=12,textvariable=nom).grid(row=0,column=0,columnspan=3)
	
	Label(CVague,text="Durée:").grid(row=1,column=1)
	Entry(CVague,width=5,textvariable=duree).grid(row=1,column=2)
	
	Label(CVague,text="Nombre:").grid(row=3,column=0)
	Label(CVague,text="Level:").grid(row=4,column=0)
	Label(CVague,image=Mob1).grid(row=2,column=1)
	Entry(CVague,width=3,textvariable=NbMob1).grid(row=3,column=1)
	Entry(CVague,width=3,textvariable=LvlMob1).grid(row=4,column=1)
	
	Label(CVague,image=Mob2).grid(row=2,column=2)
	Entry(CVague,width=3,textvariable=NbMob2).grid(row=3,column=2)
	Entry(CVague,width=3,textvariable=LvlMob2).grid(row=4,column=2)
	
	Label(CVague,text="Nombre:").grid(row=6,column=0)
	Label(CVague,text="Level:").grid(row=7,column=0)
	Label(CVague,image=Mob3).grid(row=5,column=1)
	Entry(CVague,width=3,textvariable=NbMob3).grid(row=6,column=1)
	Entry(CVague,width=3,textvariable=LvlMob3).grid(row=7,column=1)
	
	Label(CVague,image=Mob4).grid(row=5,column=2)
	Entry(CVague,width=3,textvariable=NbMob4).grid(row=6,column=2)
	Entry(CVague,width=3,textvariable=LvlMob4).grid(row=7,column=2)
	
	Button(CVague,text='Save',command=lambda: SaveConfig(vague,nom,duree,NbMob1,LvlMob1,NbMob2,LvlMob2,NbMob3,LvlMob3,NbMob4,LvlMob4)).grid(row=8,column=0)
	Button(CVague,text='Del',command=lambda: DelVague(i)).grid(row=8,column=1,columnspan=2)
	
def SaveConfig(vague,nom,duree,NbMob1,LvlMob1,NbMob2,LvlMob2,NbMob3,LvlMob3,NbMob4,LvlMob4):
	vague.nom=nom.get()
	vague.duree=duree.get()
	vague.DureeFixe=duree.get()
	vague.Mob1=NbMob1.get()
	vague.lvlMob1=LvlMob1.get()
	vague.Mob2=NbMob2.get()
	vague.lvlMob2=LvlMob2.get()
	vague.Mob3=NbMob3.get()
	vague.lvlMob3=LvlMob3.get()
	vague.Mob4=NbMob4.get()
	vague.lvlMob4=LvlMob4.get()
	
	vague.liste=[]
	if vague.Mob1>0:vague.liste.append(1)
	if vague.Mob2>0:vague.liste.append(2)
	if vague.Mob3>0:vague.liste.append(3)
	if vague.Mob4>0:vague.liste.append(4)

	print (vague.liste)
	vague.frequence=int((vague.duree*1000-3000)/(vague.Mob1+vague.Mob2+vague.Mob3+vague.Mob4))
	
	BVague.delete(0,END)
	for i,vague in enumerate(LVague):
		vague.rang=i
		BVague.insert(END, vague.nom)

def DelVague(i):
	global CVague
	CVague.grid_forget()
	CVague=Frame(F2,width=131,height=204,bg='white',bd=2,relief=GROOVE)
	CVague.pack_propagate(False)
	CVague.grid(row=1,column=0,pady=2)
	
	LVague.pop(i)
	BVague.delete(0,END)
	for i,vague in enumerate(LVague):
		BVague.insert(END, vague.nom)
	pause = 1
	fen.after(200,Relancer)
	
def Relancer():
	pause=0
	Actualisation ()

def Parametre():
	global Vie, Argent
	f=Toplevel()
	VieT=IntVar()
	VieT.set(Vie)
	ArgentT=IntVar()
	ArgentT.set(Argent)
	Label (f,text="Vie").grid(row=0,column=0)
	Entry (f,width=4,textvariable=VieT).grid(row=0,column=1)
	Label (f,text="Argent").grid(row=1,column=0)
	Entry (f,width=4,textvariable=ArgentT).grid(row=1,column=1)
	Button(f,text="OK",command=lambda:ParametreSuite(VieT,ArgentT,f)).grid(row=0,column=2)
	
def ParametreSuite(VieT,ArgentT,f):
	global Vie, Argent
	f.destroy()
	Vie=VieT.get()
	Argent=ArgentT.get()
#Fonctions de calcul de chemins
def CCDepart():
	"""CCDepart = Chercher Chemin Départ"""
	global LChemin,LCase,Sol
	LChemin=[]
	
	for case in LCase:
		Sol[case.x,case.y]=case.t

	for x in range(1,23):
		y=1
		if Sol[x,y]==2:CCSuite(x,0,x,y,[(x*29-15,-15)])
		y=20
		if Sol[x,y]==2:CCSuite(x,21,x,y,[(x*29-15,y*29+15)])
	for y in range(1,21):
		x=1
		if Sol[x,y]==1:CCSuite(0,y,x,y,[(-15,y*29-15)])
		x=22
		if Sol[x,y]==1:CCSuite(23,y,x,y,[(x*29+15,y*29-15)])
		
def CCSuite (x1,y1,x,y,chemin):

	global Sol
	if Sol[x,y]==1:
		CCVerif(x1,y1,x,y,chemin,"+x","-x")
	if Sol[x,y]==2:
		CCVerif(x1,y1,x,y,chemin,"+y","-y")
	if Sol[x,y]==3:
		CCVerif(x1,y1,x,y,chemin,"-x","+y")
	if Sol[x,y]==4:
		CCVerif(x1,y1,x,y,chemin,"-x","-y")
	if Sol[x,y]==5:
		CCVerif(x1,y1,x,y,chemin,"+x","+y")
	if Sol[x,y]==6:
		CCVerif(x1,y1,x,y,chemin,"+x","-y")
	if Sol[x,y]==7:
		CCVerif(x1,y1,x,y,chemin,"+x","-x","-y")
	if Sol[x,y]==8:
		CCVerif(x1,y1,x,y,chemin,"+x","-y",'+y')
	if Sol[x,y]==9:
		CCVerif(x1,y1,x,y,chemin,"+x","+y","-x")
	if Sol[x,y]==10:
		CCVerif(x1,y1,x,y,chemin,"-x","+y","-y")
	if Sol[x,y]==11:
		CCVerif(x1,y1,x,y,chemin,"+x","-y","-x","+y")
	
def CCVerif(x1,y1,x,y,chemin,*arg):
	global LChemin

	if "+x"in arg and not (((x+1)*29-15,y*29-15)in chemin):
	
		if Sol[x+1,y] in [1,3,4,7,9,10,11,"chateau"] and x1!=x+1 :
			if Sol[x+1,y] in [3,4,7,9,10,11,"chateau"]:chemin.append(((x+1)*29-15,y*29-15))
			if Sol[x+1,y] == "chateau":LChemin.append(chemin)
			else:CCSuite(x,y,x+1,y,chemin.copy())
	if "-x"in arg and not (((x-1)*29-15,y*29-15)in chemin):
	
		if Sol[x-1,y] in [1,5,6,7,8,9,11,"chateau"] and x1!=x-1 :
			if Sol[x-1,y] in [5,6,7,8,9,11,"chateau"]:chemin.append(((x-1)*29-15,y*29-15))
			if Sol[x-1,y] == "chateau":LChemin.append(chemin)
			else:CCSuite(x,y,x-1,y,chemin.copy())
	if "+y"in arg and not ((x*29-15,(y+1)*29-15)in chemin):
	
		if Sol[x,y+1] in [2,4,6,7,8,10,11,"chateau"]and y1!=y+1 :
			if Sol[x,y+1] in [4,6,7,8,10,11,"chateau"]:chemin.append((x*29-15,(y+1)*29-15))
			if Sol[x,y+1]== "chateau":LChemin.append(chemin)
			else:CCSuite(x,y,x,y+1,chemin.copy())
	if "-y"in arg and not ((x*29-15,(y-1)*29-15)in chemin):
	
		if Sol[x,y-1] in [2,3,5,8,9,10,11,"chateau"]and y1!=y-1 :
			if Sol[x,y-1] in [3,5,8,9,10,11,"chateau"]:chemin.append((x*29-15,(y-1)*29-15))
			if Sol[x,y-1]== "chateau":LChemin.append(chemin)
			else:CCSuite(x,y,x,y-1,chemin.copy())
	
#----------------------------------------------------------------------
#Création de la page
#----------------------------------------------------------------------

cadre=Canvas(fen,width=638,height=580)
cadre.grid(row=1,column=0,rowspan=20, columnspan=22)



#Création de la barre d'outils
BarreOutil=LabelFrame(fen,text="Barre d'outil")
BarreOutil.grid(row=0,column=0, columnspan=22)

for i in range(12):
	Radiobutton(BarreOutil,image= ICase2[i],variable=selection,value=i,indicatoron=0).grid(row=0,column=i,padx=5)
Radiobutton(BarreOutil,text="Chateau",variable=selection,value="chateau",indicatoron=0).grid(row=0,column=12,padx=5)

#ListBox des chemins
F1=LabelFrame(fen,text="Liste des chemins",padx=5,pady=5)
F1.grid(row=0,column=22,rowspan=6,pady=2,padx=2)
BChemin=Listbox(F1,bd=2,relief=GROOVE)
BChemin.pack()

#ListBox des Vagues
F2=LabelFrame(fen,text="Liste des vagues",padx=5,pady=5)
F2.grid(row=6,column=22,rowspan=15,pady=2,padx=2,sticky=N)
BVague=Listbox(F2,bd=2,relief=GROOVE)
BVague.grid(row=0,column=0)
CVague=Frame(F2,width=131,height=204,bg='white',bd=2,relief=GROOVE)
CVague.pack_propagate(False)
CVague.grid(row=1,column=0,pady=2)
Button (F2,text="Ajouter une vague",command=CreerVague).grid(row=2,column=0)

#Création de la barre de menu
BarreMenu=Menu (fen)
fen.config(menu=BarreMenu)

FileMenu= Menu(BarreMenu)
BarreMenu.add_cascade(label="Menu", menu=FileMenu)
FileMenu.add_command(label="Enregistrer",command=Enregistrer)
FileMenu.add_command(label="Enregistrer-sous",command=Enregistrer_sous)
FileMenu.add_command(label="Ouvrir",command=Ouvrir)
FileMenu.add_command(label="Parametres de la carte",command=Parametre)
FileMenu.add_command(label="Activer/Désactiver quadrillage")

#Par défault carte recouverte d'herbe et chateau au centre
for x in range(0,24):
	for y in range(0,22):
		LCase.append(Case(x,y,0,fen,cadre,selection,chateau,LCase))

Actualisation()
fen.bind_all("<Control-s>",lambda event: Enregistrer())
fen.bind_all("<Control-o>",lambda event: Ouvrir())
fen.bind_all("<Control-Alt-s>",lambda event: Enregistrer_sous())


fen.mainloop()
