#!/usr/local/bin/python
# coding: iso-8859-1
# Copyright © 2009 by Amos Newcombe
# 
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.

'''a class for turtles that use multidimensional vectors
'''

from math import sin, cos, pi
from imagelib.Drawing.Vector import Vector
from imagelib.Drawing.Drawing import Drawing, Line

xDegree = pi/180

class Turtle:
	
	# ¤ Creation
	
	dStyleDefault = {
		'pen'  : True,
		'color': '#000',
	}
	
	def __init__(self, **d):
		self.nDim = nDim = int(d.pop('dim', 2))
		self.vPos = d.pop('vPos', Vector(d.pop('lnPos', nDim)))
		self.lvHeading = d.pop('lvHeading', [Vector(*lx) for lx in d.pop('llnHeading', [
			[(1 if i+j == nDim-1 else 0) for j in range(nDim)]
			for i in range(nDim)
		])])
		for (K, V) in self.dStyleDefault.items(): d.setdefault(K, V)
		self.setStyle(d)
		self.ldState = []
		self.isCalc = False
		self.setDrawing(d.pop('drwgInit', Drawing()))
		self.dMeta = d
	
	def setStyle(self, dStyle): self.dStyle = dStyle
	def getStyle(self): return self.dStyle
	
	def set(self, sName, oVal): self.dStyle[sName] = oVal
	def get(self, sName): return self.dStyle[sName]
	
	def setDrawing(self, drwg=None): self.drwg = drwg or Drawing()
	def getDrawing(self): return self.drwg # Drawing(*self.ldDrawing, **self.dStyle)
	
	# ¤ State stack
	
	def push(self):
		d = {
			'pos'    : self.vPos.copy(),
			'heading': [v.copy() for v in self.lvHeading],
			'style'  : self.dStyle.copy(),
		}
# 		print 'push', d
		self.ldState.append(d)

	def pop(self):
		d = self.ldState.pop()
# 		print 'pop', d
		self.vPos      = d['pos']
		self.lvHeading = d['heading']
		self.dStyle    = d['style']
	
	# ¤ Motion
	
	def fd(self, x):
# 		print '%s.fd(%f)' % (self, x)
		self.move(x * self.lvHeading[0])
	
	def move(self, vDiff):
		v0 = self.vPos
		v1 = v0 + vDiff
		if not self.drwg.lContents or self.dStyle != self.drwg.lContents[-1].dStyle:
			self.getDrawing().AddContent(Line(v0, **self.dStyle))
		self.getDrawing().lContents[-1].AddPoints(v1)
		self.vPos = v1
		if self.isCalc: self.Calc()
	
	def Rotate(self, xAngle, i, j):
		print '%s.Rotate(%f, %d, %d)' % (self.__class__.__name__, xAngle, i, j)
		xAngle *= xDegree
		v0 = self.lvHeading[i].Rotate(xAngle,  self.lvHeading[j])
		v1 = self.lvHeading[j].Rotate(xAngle, -self.lvHeading[i])
		self.lvHeading[i], self.lvHeading[j] = v0, v1
		print '->', self.lvHeading

class Turtle2D(Turtle):
	
	# ¤ Creation
	
	def __init__(self, **d):
		Turtle.__init__(self, dim=2, **d)
	
	# ¤ Motion
	
	def rt(self, xAngle): self.Rotate(xAngle, 0, 1)

class Turtle3D(Turtle):
	
	# ¤ Creation
	
	def __init__(self, **d):
		Turtle.__init__(self, dim=3, **d)
	
	# ¤ Motion
	
	def pitch(self, xAngle): self.Rotate(xAngle, 1, 0)
	def roll (self, xAngle): self.Rotate(xAngle, 2, 1)
	def yaw  (self, xAngle): self.Rotate(xAngle, 0, 2)

if __name__ == '__main__':
	
	from imagelib.Drawing.PILDrawing import PILImage
	from imagelib.Drawing.SVGDrawing import SVGImage
	from imagelib.SVG.SVG import SVGDocument
	
	def Star(n, m=1, nSide=100, **dStyle):
		trtl = Turtle2D(**dStyle)
		degAlpha = m*360/n
		for i in range(n):
# 			print trtl.vPos
# 			for v in trtl.lvHeading: print '', v
			trtl.fd(nSide)
			trtl.rt(degAlpha)
		return trtl.getDrawing()
	
	drwg = Star(5, 2, 
		lnPos=[150, 150],
		llnHeading=[[0,-1], [1,0]],
	)
	
	print repr(drwg)

	PILImage('RGB', (300,300), 'white', drwg).save('Star.png')
	
	open('Star.svg', 'w').write(str(SVGDocument(xmlElem = SVGImage(
		('3in', '3in'), 
		( 300 ,  300 ), 
		drwg,
	))))
