# GVB - a GTK+/GNOME vibrations simulator
#
# Copyright (C) 2008 Pietro Battiston
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

from scipy import array, zeros, concatenate, shape, split

from dispositions import disposition
from calculators import calculators_dict

from time import time

class Points():
	def __init__(self, shape=None, gr=None, disp=None, calc=None, drawer=None, pos=None, from_file=None):
		self.number=0	#Frames numbering
		self.calculating = False

		if from_file:
			self.load(from_file)
#		print "new points"
		else:
			self.shape=shape

			if pos == None and disp:
				self.pos=disposition(shape, disp)
			else:
				self.pos = pos
				self.disp = 'flat'
			self.speeds=zeros(shape)

		self.gr=gr
		self.drawer = drawer
		self.changed = drawer.draw
		drawer.configure(self)
		self.changed()

		self.calc = calc
		if self.calc != None:
			self.calculator=calculators_dict[len(shape)][calc](shape, gr, self.pos, self.speeds)
			self.calc_time = 0
			if self.calculator.discrete:
				self.update=self.update_incremental
			else:
				self.update=self.update_given_time



	def update_incremental(self, given_time):
		calculated=False
#		print "up", given_time, self.calc_time

		while self.calc_time < given_time:
#			print "u"
			before=time()

			self.pos, self.speeds=self.calculator.update(self.pos, self.speeds, given_time)

			last_calc = time()-before

			self.number=self.number+1

			self.calc_time = self.calc_time + self.calculator.gr
			calculated=True

		if calculated:
			return last_calc*1000, self.changed()
		else:
			return None, None

	def update_given_time(self, given_time):

		before=time()

		self.pos, self.speeds = self.calculator.update(self.pos, self.speeds, given_time)

		self.last_calc = time() - before

		self.number=self.number+1

		self.calc_time = given_time

		draw_time = self.changed()

		return self.last_calc*1000, draw_time
		

	def reconfigure(self, **args):
#		print args
		if 'pos' in args:
			self.pos=args['pos']
			self.speeds=zeros(self.shape)
			self.calc_time = 0
			self.changed()
		elif 'disp' in args:
			self.disp = args['disp']
			self.pos=disposition(self.shape, self.disp)
			args['pos']=self.pos
			self.speeds=zeros(self.shape)
			self.calc_time = 0
			self.changed()
		elif 'shape' in args:
			self.shape = args['shape']
			self.pos=disposition(self.shape, self.disp)
#			print "draw!"
			self.calc_time = 0
			self.changed()
		if 'calc' in args:
			self.calc = args['calc']
			self.calculator=calculators_dict[len(self.shape)][self.calc](self.shape, self.gr, self.pos, self.speeds)
			self.calc_time = 0
			if self.calculator.discrete:
				self.update=self.update_incremental
			else:
				self.update=self.update_given_time

		elif self.calc:
			self.calculator.reconfigure(**args)

	def dump(self, filename):
		filehand = open(filename, 'w')

		for to_dump in [self.shape, self.pos, self.speeds]:
			while len(shape(to_dump)) > 1:
				to_dump = concatenate(to_dump)
			dump_string = "".join([str(number)+',' for number in to_dump])
			filehand.write(dump_string+'\n')
		filehand.close()

	def load(self, filename):
		filehand = open(filename)

		self.shape = tuple([int(number) for number in filehand.readline()[:-2].split(',')])

		self.pos = array([float(number) for number in filehand.readline()[:-2].split(',')])
		if len(self.shape) == 2:		#FIXME: not ready for dimension > 2 
			print self.pos, len(self.pos), self.shape
			self.pos = array(split(self.pos, self.shape[0]))

		self.speeds = array([float(number) for number in filehand.readline()[:-2].split(',')])
		if len(self.shape) == 2:		#FIXME: not ready for dimension > 2 
			self.speeds = array(split(self.speeds, self.shape[0]))

		print self.shape, self.pos, self.speeds
