"""
unrotate and crop images
"""

import Tkinter,sys,math,os,tempfile,string,operator
from math import *

import ArticlePanner


class UserHitQuit(Exception):
	pass


class DraggableRect:

	def __init__(self,parent,x0=None,y0=None):
		self.canvas = parent
		self.polygon = None
		self.x0 = x0
		self.y0 = y0
		self.mode = 0
		if self.x0==None:
			self.w = None
			self.h = None
			self.angle = None
			self.mode = 0
		else:
			self.mode = 1
			self.w = 0
			self.h = 0
			self.angle = 0
			self.polygon = self.canvas.create_polygon(x0,y0,x0,y0,x0,y0,x0,y0,
				fill="",width=1,outline="red")


	def reset(self):
		if self.polygon:
			self.canvas.delete(self.polygon)
		self.polygon = None
		self.angle = None
		self.x0 = None
		self.mode = 0


	def setstart(self,x0,y0):
		if self.polygon:
			self.canvas.delete(self.polygon)
		self.x0 = x0
		self.y0 = y0
		self.w = 0
		self.h = 0
		self.angle = 0
		self.mode = 1
		self.polygon = self.canvas.create_polygon(x0,y0,x0,y0,x0,y0,x0,y0,
			fill="",width=1,outline="Red")
		self.redraw()
	

	def setend(self,x1,y1):
		if self.mode==0:
			return
		if self.mode==1:
			self.w = sqrt((x1-self.x0)*(x1-self.x0)+(y1-self.y0)*(y1-self.y0))
			self.angle = atan2((y1-self.y0),(x1-self.x0))
		elif self.mode==2:
			ca,sa = cos(self.angle),sin(self.angle)
			self.h = -sa*(x1-self.x0)+ca*(y1-self.y0)
		elif self.mode==3:
			ca,sa = cos(self.angle),sin(self.angle)
			dx = ca*(x1-self.x0)+sa*(y1-self.y0)
			self.w = self.w-dx
			self.x0 = self.x0+dx*ca
			self.y0 = self.y0+dx*sa
		elif self.mode==4:
			ca,sa = cos(self.angle),sin(self.angle)
			dy = -sa*(x1-self.x0)+ca*(y1-self.y0)
			self.h = self.h-dy
			self.x0 = self.x0-dy*sa
			self.y0 = self.y0+dy*ca
		elif self.mode==5:
			ca,sa = cos(self.angle),sin(self.angle)
			self.w = ca*(x1-self.x0)+sa*(y1-self.y0)
		elif self.mode==8:
			self.w = x1-self.x0
			self.h = y1-self.y0
		elif self.mode==9:
			self.angle = -atan2(x1-self.x0,y1-self.y0)
		self.redraw()


	def click(self,x1,y1):
		if self.mode==0:
			self.reset()
			self.setstart(x1,y1)
		elif self.mode==1:
			self.mode = self.mode+1
		elif self.mode in [2,3,4,5,7,9]:
			self.mode = 6
		elif self.mode==6:
			ca = cos(self.angle)
			sa = sin(self.angle)
			cx = ca*(x1-self.x0)+sa*(y1-self.y0)
			cy = -sa*(x1-self.x0)+ca*(y1-self.y0)
			if abs(cy-self.h)<20 and -20<cx<self.w+20:
				if abs(cx)<20:
					self.mode = 9
				else:
					self.mode = 2
			elif abs(cx)<20 and -20<cy<self.h+20:
				self.mode = 3
			elif abs(cy)<20 and -20<cx<self.w+20:
				self.mode = 4
			elif abs(cx-self.w)<20 and -20<cy<self.h+20:
				self.mode = 5
			else:
				if cx<0 or cx>self.w or cy<0 or cy>self.h:
					self.reset()
					self.setstart(x1,y1)
					self.mode = 1
		else:
			self.mode = 0


	def redraw(self):
		if not self.polygon:
			return
		sa,ca = sin(self.angle),cos(self.angle)
		w,h = self.w,self.h 
		x0,y0 = self.x0,self.y0
		x1,y1 = x0+w*ca,y0+w*sa
		x2,y2 = x1-h*sa,y1+h*ca
		x3,y3 = x0-h*sa,y0+h*ca
		self.canvas.coords(self.polygon,x0,y0,x1,y1,x2,y2,x3,y3)


	def __del__(self):
		if self.polygon:
			self.canvas.delete(self.polygon)


	def getpars(self,zoomfact,height):
		if self.angle!=None:
			if self.h<0:
				flip = 1
			else:
				flip = 0
			sa,ca = sin(self.angle),cos(self.angle)
			w,h = (self.w+2)*zoomfact,(self.h+2)*zoomfact 
			x0,y0 = (self.x0-1)*zoomfact,(self.y0-1)*zoomfact
			height = (height-1)*zoomfact
			angle = self.angle
			return (angle,
				flip,
				x0,height-y0,
				x0+w*ca,height-(y0+w*sa),
				x0+w*ca-h*sa,height-(y0+w*sa+h*ca),
				x0-h*sa,height-(y0+h*ca))
		else:
			return ()


class ImagePannerWithLine(ArticlePanner.ImagePanner):
	
	def __init__(self,master,callback=None):
		ArticlePanner.ImagePanner.__init__(self,master,savebut=None)
		self.bind('<Button-1>',self.click)
		self.bind('<Motion>',self.drag)
		self.callback = callback
		self.fig = None


	def click(self,event):
		if self.callback:
			self.callback(0)
		if self.fig:
			self.fig.click(self.canvasx(event.x),
				self.canvasy(event.y))
		else:
			self.fig = DraggableRect(self,self.canvasx(event.x),
				self.canvasy(event.y))


	def drag(self,event):
		if self.fig:
			self.fig.setend(self.canvasx(event.x),
				self.canvasy(event.y))


	def duringdrag(self,event):
		try:
			self.fig.setend(self.canvasx(event.x),self.canvasy(event.y))
		except AttributeError:
			pass


	def enddrag(self,event):
		self.fig.setend(self.canvasx(event.x),self.canvasy(event.y))
		if self.callback:
			self.callback(1)


	def clear(self):
		try:
			del self.fig
		except AttributeError:
			pass


	def setimage(self,im):
		ArticlePanner.ImagePanner.setimage(self,im)
		if self.fig:
			self.fig.reset()

	
	def getpars(self,scale):
		if self.fig:
			return self.fig.getpars(scale,self.im.height())
		

class ImgCleaner(Tkinter.Frame):

	def toolbox(self):
		toolframe = Tkinter.Frame(self)
		self.okbut = Tkinter.Button(toolframe,text="Ok",command=self.ok)
		self.okbut.pack(side=Tkinter.LEFT)
		self.canbut = Tkinter.Button(toolframe,text="Image bad",command=self.cancel)
		self.canbut.pack(side=Tkinter.LEFT)
		self.newNameIn = Tkinter.Entry(toolframe, width=20)
		self.newNameIn.pack(side=Tkinter.LEFT)
		Tkinter.Label(toolframe,text=" ").pack(side=Tkinter.LEFT,
			fill=Tkinter.X,expand=1)
		self.quitbut = Tkinter.Button(toolframe,text="Quit",command=self.endthis)
		self.quitbut.pack(side=Tkinter.LEFT)
		return toolframe


	def ok(self):
		if self.newNameIn.get():
			self.newName = self.newNameIn.get()
		else:
			self.newName = self.imname
		self.valid = 1
		self.quit()


	def cancel(self):
		self.valid = None
		self.quit()

	
	def endthis(self):
		self.doquit = 1
		self.quit()


	def __init__(self,parent):
		Tkinter.Frame.__init__(self,parent)
		self.bind("q", lambda ev: self.endthis())
		self.focus_force()
		self.config(width=900,height=1100)
		self.pack_propagate(0)
		self.imscale = 8 
		self.impan = ImagePannerWithLine(self,callback=self.have_line)
		self.impan.pack(expand=1,fill=Tkinter.BOTH,side=Tkinter.TOP)
		self.impan.bind("<Button-3>",lambda a,self=self:self.ok())
		self.toolbox().pack(expand=0,fill=Tkinter.X,side=Tkinter.TOP)
		self.imname = None
		self.tempfl = tempfile.mktemp()
		self.fig = None
		self.valid = None
		self.doquit = None


	def setim(self,imname):
		open(imname)
		self.impan.setimage(ArticlePanner.makepic(imname,scale=self.imscale))
		self.imname = imname
		self.valid = None
		self.newNameIn.delete(0, Tkinter.END)


	def getpars(self):
		return self.impan.getpars(self.imscale)+(self.newName,)

	
	def __del__(self):
		try:
			os.unlink(self.tempfl)
		except os.error:
			pass
	

	def have_line(self,a):
		pass


import tiff

def makecommand(fname, rotcrop):
	if len(rotcrop)==1:
		return "mv %s good/%s"%(fname,rotcrop[0])
	t = tiff.tiff(fname)
	cx,cy = t.width/2,t.height/2
	croppath = []
	for i in range(1,(len(rotcrop))/2):
		croppath.append("%f,%f"%(rotcrop[2*i],rotcrop[2*i+1]))
	if croppath:
		croppath = string.join(croppath," ")
	else:
		croppath = ""
	if rotcrop[1]:
		angle = -rotcrop[0]+3.14159
	else:
		angle = -rotcrop[0]

	return "echo processing %s; unrotate.py %s %f %s;mv %s %s\n"%(fname,
		fname, angle, croppath, fname, "good/%s.tiff"%rotcrop[-1])
		

def quitnow():
	raise UserHitQuit,"Window Closing"


if __name__=="__main__":
	root = Tkinter.Tk()
	root.protocol("WM_DELETE_WINDOW",quitnow)
	root.title("Image Cleanup")
	cl = ImgCleaner(root)
	cl.pack(expand=1,fill=Tkinter.BOTH)
	cutscript = ["mkdir good bad > /dev/null 2>&1"]
	try:
		for a in sys.argv[1:]:
			if a[-5:]==".orig" or not os.path.isfile(a):
				sys.stderr.write("%s skipped\n"%a)
				continue
			root.title("Image Cleanup: %s"%a)
			cl.setim(a)
			cl.mainloop()
			if cl.doquit:
				quitnow()
			if cl.valid:
				cutscript.append(makecommand(a,cl.getpars()))
			else:
				cutscript.append("mv %s bad"%a)
	except UserHitQuit:
		pass
	root.withdraw()
	try:
		open(".tmpscript","w").write(string.join(cutscript,"\n"))
		try:
			os.chmod(".tmpscript",0664)
		except os.error:
			pass
	except IOError:
		pass
	os.popen("sh","w").write(string.join(cutscript,"\n"))
