from qtpy import QtCore as QC
from qtpy import QtWidgets as QW

from hydrus.client import ClientConstants as CC
from hydrus.client import ClientGlobals as CG
from hydrus.client.gui import ClientGUIFunctions
from hydrus.client.gui import QtPorting as QP
from hydrus.client.gui.widgets import ClientGUICommon

AUDIO_GLOBAL = 0
AUDIO_MEDIA_VIEWER = 1
AUDIO_PREVIEW = 2

volume_types_str_lookup = {}

volume_types_str_lookup[ AUDIO_GLOBAL ] = 'global'
volume_types_str_lookup[ AUDIO_MEDIA_VIEWER ] = 'media viewer'
volume_types_str_lookup[ AUDIO_PREVIEW ] = 'preview'

volume_types_to_option_names = {}

volume_types_to_option_names[ AUDIO_GLOBAL ] = ( 'global_audio_mute', 'global_audio_volume' )
volume_types_to_option_names[ AUDIO_MEDIA_VIEWER ] = ( 'media_viewer_audio_mute', 'media_viewer_audio_volume' )
volume_types_to_option_names[ AUDIO_PREVIEW ] = ( 'preview_audio_mute', 'preview_audio_volume' )

def ChangeVolume( volume_type, volume ):
    
    ( mute_option_name, volume_option_name ) = volume_types_to_option_names[ volume_type ]
    
    CG.client_controller.new_options.SetInteger( volume_option_name, volume )
    
    CG.client_controller.pub( 'new_audio_volume' )
    
def FlipMute( volume_type ):
    
    ( mute_option_name, volume_option_name ) = volume_types_to_option_names[ volume_type ]
    
    CG.client_controller.new_options.FlipBoolean( mute_option_name )
    
    CG.client_controller.pub( 'new_audio_mute' )
    
def SetMute( volume_type, mute ):
    
    ( mute_option_name, volume_option_name ) = volume_types_to_option_names[ volume_type ]
    
    CG.client_controller.new_options.SetBoolean( mute_option_name, mute )
    
    CG.client_controller.pub( 'new_audio_mute' )
    
class AudioMuteButton( ClientGUICommon.BetterBitmapButton ):
    
    def __init__( self, parent, volume_type ):
        
        self._volume_type = volume_type
        
        pixmap = self._GetCorrectPixmap()
        
        ClientGUICommon.BetterBitmapButton.__init__( self, parent, pixmap, FlipMute, self._volume_type )
        
        CG.client_controller.sub( self, 'UpdateMute', 'new_audio_mute' )
        
    
    def _GetCorrectPixmap( self ):
        
        ( mute_option_name, volume_option_name ) = volume_types_to_option_names[ self._volume_type ]
        
        if CG.client_controller.new_options.GetBoolean( mute_option_name ):
            
            pixmap = CC.global_pixmaps().mute
            
        else:
            
            pixmap = CC.global_pixmaps().sound
            
        
        return pixmap
        
    
    def UpdateMute( self ):
        
        pixmap = self._GetCorrectPixmap()
        
        ClientGUIFunctions.SetBitmapButtonBitmap( self, pixmap )
        
    
class VolumeControl( QW.QWidget ):
    
    def __init__( self, parent, canvas_type, direction = 'down' ):
        
        QW.QWidget.__init__( self, parent )
        
        self._canvas_type = canvas_type
        
        self._global_mute = AudioMuteButton( self, AUDIO_GLOBAL )
        
        self._global_mute.setToolTip( 'Global mute/unmute' )
        self._global_mute.setFocusPolicy( QC.Qt.NoFocus )
        
        vbox = QP.VBoxLayout( margin = 0, spacing = 0 )
        
        QP.AddToLayout( vbox, self._global_mute, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
        
        self.setLayout( vbox )
        
        self._popup_window = self._PopupWindow( self, canvas_type, direction = direction )
        
    
    def enterEvent( self, event ):
        
        if not self.isVisible():
            
            return
            
        
        self._popup_window.DoShowHide()
        
        event.ignore()
        
    
    def leaveEvent( self, event ):
        
        if not self.isVisible():
            
            return
            
        
        self._popup_window.DoShowHide()
        
        event.ignore()
        
    
    def PopupIsVisible( self ):
        
        return self._popup_window.isVisible()
        
    
    class _PopupWindow( QW.QFrame ):
        
        def __init__( self, parent, canvas_type, direction = 'down' ):
            
            QW.QFrame.__init__( self, parent )
            
            self._canvas_type = canvas_type
            
            self._direction = direction
            
            self.setWindowFlags( QC.Qt.Tool | QC.Qt.FramelessWindowHint )
            
            self.setAttribute( QC.Qt.WA_ShowWithoutActivating )
            
            if self._canvas_type in CC.CANVAS_MEDIA_VIEWER_TYPES:
                
                option_to_use = 'media_viewer_uses_its_own_audio_volume'
                volume_type = AUDIO_MEDIA_VIEWER
                
            else:
                
                option_to_use = 'preview_uses_its_own_audio_volume'
                volume_type = AUDIO_PREVIEW
                
            
            self._specific_mute = AudioMuteButton( self, volume_type )
            
            self._specific_mute.setToolTip( 'Mute/unmute: {}'.format( CC.canvas_type_str_lookup[ self._canvas_type ] ) )
            
            if CG.client_controller.new_options.GetBoolean( option_to_use ):
                
                slider_volume_type = volume_type
                
            else:
                
                slider_volume_type = AUDIO_GLOBAL
                
            
            self._volume = VolumeSlider( self, slider_volume_type )
            
            vbox = QP.VBoxLayout()
            
            if self._direction == 'down':
                
                QP.AddToLayout( vbox, self._specific_mute, CC.FLAGS_CENTER )
                QP.AddToLayout( vbox, self._volume, CC.FLAGS_CENTER )
                
            else:
                
                QP.AddToLayout( vbox, self._volume, CC.FLAGS_CENTER )
                QP.AddToLayout( vbox, self._specific_mute, CC.FLAGS_CENTER )
                
            
            #vbox.setAlignment( self._volume, QC.Qt.AlignHCenter )
            #vbox.setAlignment( self._specific_mute, QC.Qt.AlignHCenter )
            
            self.setLayout( vbox )
            
            self.hide()
            
            self.adjustSize()
            
            CG.client_controller.sub( self, 'NotifyNewOptions', 'notify_new_options' )
            
        
        def DoShowHide( self ):
            
            parent = self.parentWidget()
            
            horizontal_offset = ( self.width() - parent.width() ) // 2 
            
            if self._direction == 'down':
                
                pos = parent.mapToGlobal( parent.rect().bottomLeft() )
                
            else:
                
                pos = parent.mapToGlobal( parent.rect().topLeft() - self.rect().bottomLeft() )
                
            
            pos.setX( pos.x() - horizontal_offset )
            
            self.move( pos )
            
            over_parent = ClientGUIFunctions.MouseIsOverWidget( parent )
            over_me = ClientGUIFunctions.MouseIsOverWidget( self )
            
            should_show = over_parent or over_me
            
            if should_show:
                
                self.show()
                
            else:
                
                self.hide()
                
            
        
        def leaveEvent( self, event ):
            
            if not self.isVisible():
                
                return
                
            
            self.DoShowHide()
            
            event.ignore()
            
        
        def NotifyNewOptions( self ):
            
            if self._canvas_type in CC.CANVAS_MEDIA_VIEWER_TYPES:
                
                option_to_use = 'media_viewer_uses_its_own_audio_volume'
                volume_type = AUDIO_MEDIA_VIEWER
                
            else:
                
                option_to_use = 'preview_uses_its_own_audio_volume'
                volume_type = AUDIO_PREVIEW
                
            
            if CG.client_controller.new_options.GetBoolean( option_to_use ):
                
                slider_volume_type = volume_type
                
            else:
                
                slider_volume_type = AUDIO_GLOBAL
                
            
            if slider_volume_type != self._volume.GetVolumeType():
                
                self._volume.SetVolumeType( slider_volume_type )
                
            
        
    
class VolumeSlider( QW.QSlider ):
    
    def __init__( self, parent, volume_type ):
        
        QW.QSlider.__init__( self, parent )
        
        self._volume_type = volume_type
        
        self.setOrientation( QC.Qt.Vertical )
        self.setTickInterval( 1 )
        self.setTickPosition( QW.QSlider.TicksBothSides )
        self.setRange( 0, 100 )
        
        volume = self._GetCorrectValue()
        
        self.setValue( volume )
        
        self.valueChanged.connect( self._VolumeSliderMoved )
        
    
    def _GetCorrectValue( self ):
        
        ( mute_option_name, volume_option_name ) = volume_types_to_option_names[ self._volume_type ]
        
        return CG.client_controller.new_options.GetInteger( volume_option_name )
        
    
    def _VolumeSliderMoved( self ):
        
        ChangeVolume( self._volume_type, self.value() )
        
    
    def GetVolumeType( self ):
        
        return self._volume_type
        
    
    def SetVolumeType( self, volume_type ):
        
        self._volume_type = volume_type
        
        volume = self._GetCorrectValue()
        
        self.setValue( volume )
        
    
    def UpdateMute( self ):
        
        volume = self._GetCorrectValue()
        
        self.setValue( volume )
        
    
