# -*- coding: utf-8 -*-
"""
Module d'analyse des fichiers de log minwii.

$Id$
$URL$
"""

from logfilereader import LogFileReader
from pprint import pprint
from musicxml import musicXml2Song
from statlib import stats

DEFAULT_STATS = ('geometricmean',
                 'harmonicmean',
                 'mean',
                 'median',
                 'medianscore',
                 #'mode',
                 'moment',
                 'variation',
                 'skew',
                 'kurtosis',
                 #'itemfreq',
                 #'histogram',
                 #'cumfreq',
                 #'relfreq',
                 )

def statsresults(m) :
    def computeList(self):
        l = m(self)
        ret = {}
        for name in DEFAULT_STATS :
            ret[name] = getattr(stats, name)(l)
        return ret
    return computeList

class LogFileAnalyser(LogFileReader) :

    POSSIBLE_ANALYSES = {'BEGINNER' : ('songDuration',
                                       'playingDuration',
                                       'noteEndNoteOnLatency',
                                       'realisationRate')
                        ,'EASY'     : ('songDuration',
                                       'playingDuration',
                                       'noteEndNoteOnLatency',
                                       'realisationRate',
                                       'missCount')
                        ,'NORMAL'   : ('songDuration',
                                       'playingDuration',
                                       'realisationRate',
                                       'missCount')
                        ,'ADVANCED' : ('songDuration',
                                       'playingDuration',
                                       'realisationRate',
                                       'missCount')
                        ,'EXPERT'   : ('songDuration',
                                       'playingDuration',
                                       'realisationRate',
                                       'missCount')
                        }
    
    def analyse(self) :
        self.mode = mode = self.getMode()
        print 'Mode :', mode
        
        results = {}
        
        for name in self.POSSIBLE_ANALYSES[mode] :
            meth = getattr(self, name)
            results[name] = meth()
        
        return results
    
    def playingDuration(self) :
        """ retourne la durée écoulée entre le premier et de dernier message
            de type événement : correspond à la durée d'interprétation.
        """
        last = self.getLastEventTicks()
        first = self.getFirstEventTicks()
        return last - first
    
    def songDuration(self) :
        """ retourne la durée de référence de la chanson
            en prenant en compte le tempo présent dans la transcription
            et en effectuant toutes les répétitions des couplets / refrains.
        """
        songFile = self.getSongFile()
        song = musicXml2Song(songFile)
        duration = 0
        for note, verseIndex in song.iterNotes() :
            duration = duration + note.duration
        return duration * song.quarterNoteDuration
    
    @statsresults
    def noteEndNoteOnLatency(self) :
        eIter = self.getEventsIterator()
        latencies = []
        lastnoteEndT = 0
        
        for ticks, eventName, message in eIter :
            if eventName == 'NOTEEND':
                lastnoteEndT = ticks
            if eventName == 'NOTEON' and lastnoteEndT :
                latencies.append(ticks - lastnoteEndT)
        
        return latencies
    
    def noteOnCount(self) :
        "retourne le nombre d'événements NOTEON"
        
        eIter = self.getEventsIterator()
        cpt = 0        

        for ticks, eventName, message in eIter :
            if eventName == 'NOTEON' :
                cpt = cpt + 1
        
        return cpt
    
    def realisationRate(self) :
        """ taux de réalisation en nombre de note
            peut être supérieur à 100 % car la chanson
            boucle à l'infini.
        """
        songFile = self.getSongFile()
        song = musicXml2Song(songFile)
        songNoteCpt = 0
        for note, verseIndex in song.iterNotes() :
            songNoteCpt = songNoteCpt + 1
        
        return int(round(self.noteOnCount() / float(songNoteCpt) * 100, 0))
    
    def missCount(self) :
        eIter = self.getEventsIterator()
        miss = 0
        if self.mode in ('EASY', 'NORMAL') :
            catchColUp = False
            for ticks, eventName, message in eIter :
                if eventName == 'COLDOWN' :
                    colState = message.split(None, 2)[1]
                    colState = colState == 'True'
                    if colState :
                        catchColUp = False
                        continue
                    else :
                        catchColUp = True
                elif eventName == 'NOTEON' :
                    catchColUp = False
                elif eventName == 'COLUP' and catchColUp :
                    miss = miss + 1
        else :
            for ticks, eventName, message in eIter :
                if eventName == 'COLDOWN' :
                    colState = message.split(None, 2)[1]
                    colState = colState == 'True'
                    if not colState :
                        miss = miss + 1
        
        return miss
                
        
        
        

def main() :
    from optparse import OptionParser
    usage = "%prog logfile"
    op = OptionParser(usage)
    options, args = op.parse_args()
    if len(args) != 1 :
        op.error("incorrect number of arguments")


    lfa = LogFileAnalyser(args[0])
    pprint(lfa.analyse())

if __name__ == "__main__" :
    from os.path import realpath, sep
    import sys
    minwiipath = realpath(__file__).split(sep)
    minwiipath = minwiipath[:-2]
    minwiipath = sep.join(minwiipath)
    sys.path.insert(1, minwiipath)
    main()
