# GVB - a GTK+/GNOME vibrations simulator
#
# Copyright © 2008-2013 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)
        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.invalidate
        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

        while self.calc_time < given_time:
            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:
            self.changed()
            return last_calc*1000
        else:
            return 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

        self.changed()

        return self.last_calc*1000
        

    def reconfigure(self, **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)
            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 
            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]))

