import sounddevice as sd
import numpy as np
import comtypes
import comtypes.client
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import json

class WindowsAudioManager:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.init()
        return cls._instance
    def init(self):
        """
        Initialize Windows audio device and volume management.
        """
        self.devices = sd.query_devices()
        self.default_input = sd.default.device[0]
        self.default_output = sd.default.device[1]
    
    def list_audio_devices(self, kind='input'):
        """
        List available audio devices.
        
        :param kind: 'input' or 'output'
        :return: List of audio devices
        """
        if kind == 'input':
            return [
                {
                    'index': dev['index'], 
                    'name': dev['name'], 
                    'max_input_channels': dev['max_input_channels'],
                    'default_samplerate': dev['default_samplerate']
                } 
                for dev in self.devices if dev['max_input_channels'] > 0
            ]
        elif kind == 'output':
            return [
                {
                    'index': dev['index'], 
                    'name': dev['name'], 
                    'max_output_channels': dev['max_output_channels'],
                    'default_samplerate': dev['default_samplerate']
                } 
                for dev in self.devices if dev['max_output_channels'] > 0
            ]
    def get_default_device(self, kind='input'):
        """
        Get the default audio device.
        
        :param kind: 'input' or 'output'
        :return: Default audio device information
        """
        if kind == 'input':
            dev = self.devices[self.default_input]
            return [
                {
                    'index': dev['index'], 
                    'name': dev['name'], 
                    'max_input_channels': dev['max_input_channels'],
                    'default_samplerate': dev['default_samplerate']
                } 
            ]
        
    def set_default_input_device(self, device_index):
        if(device_index is None):
            return self.get_current_input_device_sample_rate()
        """
        Set the default input audio device.
        
        :param device_index: Index of the audio device
        :return: Sample rate of the selected device
        """
        sd.default.device[0] = device_index
        self.default_input = device_index
        
        # Get the sample rate of the selected device
        device_info = sd.query_devices(device_index)
        return device_info['default_samplerate']
    
    def get_current_input_device_sample_rate(self):
        """
        Get the sample rate of the current input device.
        
        :return: Sample rate of the current input device
        """
        device_info = sd.query_devices(self.default_input)
        return device_info['default_samplerate']
    
    def get_system_volume(self):
        """
        Get the system master volume.
        
        :return: Current system volume (0.0 to 1.0)
        """
        devices = AudioUtilities.GetSpeakers()
        interface = devices.Activate(
            IAudioEndpointVolume._iid_, 
            CLSCTX_ALL, 
            None
        )
        volume = interface.QueryInterface(IAudioEndpointVolume)
        return volume.GetMasterVolumeLevelScalar()
    
    def set_system_volume(self, volume_level):
        """
        Set the system master volume.
        
        :param volume_level: Volume level (0.0 to 1.0)
        """
        devices = AudioUtilities.GetSpeakers()
        interface = devices.Activate(
            IAudioEndpointVolume._iid_, 
            CLSCTX_ALL, 
            None
        )
        volume = interface.QueryInterface(IAudioEndpointVolume)
        volume.SetMasterVolumeLevelScalar(volume_level, None)