# -*- coding: utf-8 -*-
"""
l'application winwii

$Id$
$URL$
"""

import pygame
from pgu.gui import Theme
from pgu.gui import Desktop
from pgu.gui import QUIT
from minwii.widgets.launch import LaunchScreen
from minwii.widgets.home import Home
from minwii.widgets.playingscreen import SongPlayingScreen, PlayingScreen
from minwii.widgets.instrumentselector import InstrumentSelector
from minwii.synth import Synth
from minwii.eventutils import EventDispatcher
from minwii.musicxml import musicXml2Song
from minwii.config import SONG_FILE_PATH
from minwii.config import SCREEN_RESOLUTION
from minwii.globals import PLAYING_MODES_DICT
from minwii.log import console, LOG_FORMAT_VERSION, envLogger
import os.path

wiiuse = None
pygame_wiimouse = None

SCREEN_HOME         = 0
SCREEN_INSTRUMENTS  = 1
SCREEN_PLAY         = 2



class MinWii(object):
    
    def __init__(self, wiimoteSupport=True, fullscreen=False, audioDriver=None) :
        envLogger.info('winwii log format version : %s', LOG_FORMAT_VERSION)
        self.wiimoteSupport = wiimoteSupport
        self.fullscreen = fullscreen
        LaunchScreen()
        themedir = os.path.join(os.path.dirname(__file__), 'widgets', 'data', 'minwii_theme')
        theme = Theme(themedir)
        self.app = Desktop(theme=theme)
        self.synth = Synth(driver=audioDriver)
        self.screenResolution = SCREEN_RESOLUTION
        envLogger.info('résolution écran : %s', self.screenResolution)
        self.nwiimotes = 0
        self.initWiimotes()
        self.firstSong = True
        self.screen = SCREEN_HOME
        self.playingScreen = None
    
    def initWiimotes(self) :
        if self.wiimoteSupport :
            global wiiuse
            from pywiiuse import PyWiiUse as wiiuse
            global pygame_wiimouse
            from pywiiuse import pygame_wiimouse
            from minwii.config import IR_POSITION
            pygame_wiimouse.init(5, 5, self.screenResolution, IR_POSITION) # look for 5, wait 5 seconds
            self.nwiimotes = nwiimotes = pygame_wiimouse.get_count()
            console.debug('wiimotes found : %d', nwiimotes)
            self.WT = WT = pygame_wiimouse.WT
            WT.setEventCallBack(self._wiimotesEventCallBack)
            WT.pause()
        else :
            self.WT = _WTFacade()
    
    def _wiimotesEventCallBack(self, wt, id, wmp) :
        if self.screen == SCREEN_PLAY :
            pygame_wiimouse._default_event_cb(wt, id, wmp)
            
            wm = wmp[0]
            if id == self.nwiimotes - 1 :
                # le bouton Home de la télécommande permet de sortir
                # (envoi d'un événement clavier « q »)
                if wiiuse.is_just_pressed(wm, wiiuse.button['Home']) :
                    event = pygame.event.Event(pygame.KEYDOWN,
                                               key = pygame.K_q,
                                               unicode = u'q')
                    pygame.event.post(event)
                elif wiiuse.is_just_pressed(wm, wiiuse.button['+']) :
                    self.synth.inc_gain()
                elif wiiuse.is_just_pressed(wm, wiiuse.button['-']) :
                    self.synth.dec_gain()
                elif wiiuse.is_just_pressed(wm, wiiuse.button['1']) and self.playingScreen :
                    self.playingScreen.tempoTrimUp()
                elif wiiuse.is_just_pressed(wm, wiiuse.button['2']) and self.playingScreen :
                    self.playingScreen.tempoTrimDown()

        elif self.screen in (SCREEN_HOME, SCREEN_INSTRUMENTS) :
            pygame_wiimouse._full_mouse_event_cb(wt, id, wmp)
    
    def run(self) :
        "séquençage de l'affichage des écrans"
        displayFlags = 0
        if self.fullscreen :
            displayFlags = displayFlags | pygame.FULLSCREEN
        pygame.display.set_mode(self.screenResolution, displayFlags)
        pygame.display.set_caption('MINDs')
        WT = self.WT
        
        # valeurs par défaut des options
        songFile, playMode, displayNotes, wiimoteIndex = '', 'NORMAL', False, 0

        while True :
            WT.resume()
            WT.selectWiimote(self.nwiimotes - 1) # la télécommande est la souris
            self.screen = SCREEN_HOME
            exit, songFile, playMode, displayNotes, wiimoteIndex = \
                self.selectSongAndOptions(songFile, playMode, displayNotes, wiimoteIndex)
            if exit :
                WT.quit()
                break
            
            
            self.screen = SCREEN_INSTRUMENTS
            instrumentDescription = self.selectInstrument()
            if not instrumentDescription :
                continue
            
            self.screen = SCREEN_PLAY
            WT.selectWiimote(wiimoteIndex)
            self.runPlayingScreen(songFile, playMode, displayNotes, instrumentDescription)
            WT.pause()
    
    
    def selectSongAndOptions(self, songFile, playMode, displayNotes, wiimoteIndex) :
        """ lance l'écran de paramétrage et retourne un tuple comportant :
            - drapeau de sortie de l'application (booléen)
            - chemin du fichier de la chanson
            - mode (entier)
            - affichage des notes (booléen)
            - wiimote sélectionnée (entier)
        """
        home = Home(songPath=SONG_FILE_PATH,
                    songFile=songFile,
                    playMode=playMode,
                    displayNotes=displayNotes,
                    wiimoteIndex=wiimoteIndex,
                    nwiimotes=self.nwiimotes)
        app = self.app
        home.connect(QUIT, app.quit)
        app.run(home)
        app.close(home)
        
        #logging
        if home.exitApp :
            console.debug("sortie de l'application")
        else :
            actual_wiimotes = self.WT.get_count()
            if self.firstSong :
                self.firstSong = False
            else :
                envLogger.info('NEW_LOG_FILE')
            console.info('chanson : %s', home.songFile)
            console.info('mode : %s', home.modeSelect.value)
            if actual_wiimotes is None :
                console.info('HID : souris')
            elif actual_wiimotes == 0 :
                console.info('HID : souris (pas de wiimote trouvée)')
            else :
                console.info('HID : wiimote %d', home.selectedWiimote.value + 1)
        #---
        
        return (home.exitApp,
                home.songFile,
                home.selectedPlayMode,
                home.displayNotes,
                home.selectedWiimoteIndex)
    
    def selectInstrument(self) :
        """ lance l'écran de sélection de l'instrument et retourne
            un dictionnaire comportant la description de l'instrument
        """
        selector = InstrumentSelector()
        selector.run()
        selector.stop()
        pygame.event.clear()
        EventDispatcher.reset()
        instru = selector.selectedInstrument
        if instru :
            console.info('instrument : %s', instru['name'])
            console.info('preset : %d', instru['preset'])
            console.info('bank : %d', instru['bank'])
            console.info('ajustement octave : %d', instru['octave'])
        return instru
    
    def runPlayingScreen(self, songFile, playMode, displayNotes, instrumentDescription) :
        """ Lance l'écran de jeu principal avec la chanson 'songFile' dans le mode 'playMode'
            avec l'instrument midi 'instrumentDescription'.
        """
        playMode = PLAYING_MODES_DICT[playMode]
        bank, preset = instrumentDescription['bank'], instrumentDescription['preset']
        octave = instrumentDescription['octave']
        self.synth.adjust_octave(0, octave)
        self.synth.program_select(0, bank, preset)
        if playMode == PLAYING_MODES_DICT['IMPRO'] :
            playingScreen = PlayingScreen(self.synth, displayNotes=displayNotes)
        else :
            song = musicXml2Song(songFile)
            self.playingScreen = playingScreen = SongPlayingScreen(self.synth, song, mode=playMode, displayNotes=displayNotes)
        playingScreen.run()
        pygame.event.clear()
        EventDispatcher.reset()
        self.playingScreen = None


class _WTFacade :
    """ Classe utilitaire pour singer l'api
        de pygame_wiimouse en cas d'abscence de wiimote.
    """
    selectWimoteIndex = 0
    def pause(self):
        pass
    def resume(self):
        pass
    def selectWiimote(self, i):
        pass
    def get_count(self) :
        return None
    def quit(self) :
        pass
