# -*- coding: utf-8 -*-
"""
Boîte de dialogue pour sélection des chansons.

$Id$
$URL$
"""

from pgu.gui import FileDialog
import os
import tempfile
from xml.etree import ElementTree
from minwii.musicxml import musicXml2Song

INDEX_TXT = 'index.txt'

class FileOpenDialog(FileDialog):
    
    
    
    def __init__(self, path):
        FileDialog.__init__(self, 
                            title_txt="Ouvrir une chanson",
                            button_txt="Ouvrir",
                            path=path,
                            )
    
    def _list_dir_(self):
        self.input_dir.value = self.curdir
        self.input_dir.pos = len(self.curdir)
        self.input_dir.vpos = 0
        dirs = []
        files = []
        try:
            for i in os.listdir(self.curdir):
                if i.startswith('.') : continue
                if os.path.isdir(os.path.join(self.curdir, i)): dirs.append(i)
                else: files.append(i)
        except:
            self.input_file.value = "Dossier innacessible !"

        dirs.sort()
        dirs.insert(0, '..')

        files.sort()
        for i in dirs:
            self.list.add(i, image=self.dir_img, value=i)
        
        xmlFiles = []
        for i in files:
            if not i.endswith('.xml') :
                continue
            filepath = os.path.join(self.curdir, i)
            xmlFiles.append(filepath)
            # self.list.add(FileOpenDialog.getSongTitle(filepath), value=i)
        
        if xmlFiles :
            printableLines = self.getPrintableLines(xmlFiles)
            for l in printableLines :
                self.list.add(l[0], value = l[1])
 
        self.list.set_vertical_scroll(0)
    
    def getPrintableLines(self, xmlFiles) :
        index = self.getUpdatedIndex(xmlFiles)

        printableLines = []
        for l in index :
            l = l.strip()
            l = l.split('\t')
            printableLines.append(('%s - %s / %s' % (l[2], l[3], l[4]), l[0]))
        
        return printableLines
    
    
    @staticmethod
    def getSongTitle(file) :
        it = ElementTree.iterparse(file, ['start', 'end'])
        creditFound = False
        title = os.path.basename(file)
        
        for evt, el in it :
            if el.tag == 'credit' :
                creditFound = True
            if el.tag == 'credit-words' and creditFound:
                title = el.text
                break
            if el.tag == 'part-list' :
                # au delà de ce tag : aucune chance de trouver un titre
                break
        return title
    
    @staticmethod
    def getSongMetadata(file) :
        metadata = {}
        metadata['title'] = FileOpenDialog.getSongTitle(file).encode('iso-8859-1')
        metadata['mtime'] = str(os.stat(file).st_mtime)
        metadata['file'] = os.path.basename(file)
        song = musicXml2Song(file)
        metadata['distinctNotes'] = len(song.distinctNotes)
        
        histo = song.intervalsHistogram
        coeffInter = reduce(lambda a, b : a + b,
                            [abs(k) * v for k, v in histo.items()])

        totInter = reduce(lambda a, b: a+b, histo.values())
        totInter = totInter - histo.get(0, 0)
        difficulty = int(round(float(coeffInter) / totInter, 0))
        metadata['difficulty'] = difficulty

        return metadata
    
    def getUpdatedIndex(self, xmlFiles) :
        indexTxtPath = os.path.join(self.curdir, INDEX_TXT)
        index = []
        
        if not os.path.exists(indexTxtPath) :
            musicXmlFound = False
            tmp = tempfile.TemporaryFile(mode='r+')
            for file in xmlFiles :
                try :
                    metadata = FileOpenDialog.getSongMetadata(file)
                    musicXmlFound = True
                except ValueError, e :
                    print e
                    if e.args and e.args[0] == 'not a musicxml file' :
                        continue
                
                line = '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
                index.append(line)
                tmp.write(line)
            
            if musicXmlFound :
                tmp.seek(0)
                indexFile = open(indexTxtPath, 'w')
                indexFile.write(tmp.read())
                indexFile.close()
            tmp.close()
        else :
            indexedFiles = {}
            indexTxt = open(indexTxtPath, 'r')

            # check if index is up to date, and update entries if so.
            for l in filter(None, indexTxt.readlines()) :
                parts = l.split('\t')
                fileBaseName, modificationTime = parts[0], parts[1]
                filePath = os.path.join(self.curdir, fileBaseName)

                if not os.path.exists(filePath) :
                    continue

                indexedFiles[fileBaseName] = l
                currentMtime = str(os.stat(filePath).st_mtime)
                
                # check modification time missmatch
                if currentMtime != modificationTime :
                    try :
                        metadata = FileOpenDialog.getSongMetadata(filePath)
                        musicXmlFound = True
                    except ValueError, e :
                        print e
                        if e.args and e.args[0] == 'not a musicxml file' :
                            continue
                    
                    metadata = FileOpenDialog.getSongMetadata(filePath)
                    line = '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
                    indexedFiles[fileBaseName] = line
            
            # check for new files.
            for file in xmlFiles :
                fileBaseName = os.path.basename(file)
                if not indexedFiles.has_key(fileBaseName) :
                    try :
                        metadata = FileOpenDialog.getSongMetadata(filePath)
                        musicXmlFound = True
                    except ValueError, e :
                        print e
                        if e.args and e.args[0] == 'not a musicxml file' :
                            continue
                
                    metadata = FileOpenDialog.getSongMetadata(file)
                    line = '%(file)s\t%(mtime)s\t%(title)s\t%(distinctNotes)d\t%(difficulty)d\n' % metadata
                    indexedFiles[fileBaseName] = line
            
            # ok, the index is up to date !
            
            index = indexedFiles.values()
            index.sort()
            
        
        return index
        