import os
import json

from platformdirs import user_data_dir
from audio_io import AudioIO
from windows_audio import WindowsAudioManager

class SettingsManager:
    _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):
        # read settings file from executing directory
        print("Initializing SettingsManager", os.getcwd())
        file_path = user_data_dir("ClipTrim")
        os.makedirs(file_path, exist_ok=True)
        self.settings_file = os.path.join(file_path, "settings.json")
        if os.path.exists(self.settings_file):
            with open(self.settings_file, "r") as f:
                self.settings = json.load(f)
        else:
            self.settings = {
                "input_device": None,
                "output_device": None,
                "save_path": os.path.join(file_path, "recordings"),
                "recording_length": 15
            }
        audio_manager = WindowsAudioManager()

        input_devices = audio_manager.list_audio_devices('input') 
        output_devices = audio_manager.list_audio_devices('output')
        # print("Available input devices:")
        # for i, dev in enumerate(input_devices):
        #     print(i, dev['name'])
        # print("Available output devices:")
        # for i, dev in enumerate(output_devices):
        #     print(i, dev['name'])
        # print(f"Available input devices: {input_devices}")
        # print(f"Available output devices: {output_devices}")
        input = None
        output = None

        if("input_device" in self.settings):
            input = self.settings["input_device"]
        if("output_device" in self.settings):
            output = self.settings["output_device"]
        #see if input device is in "devices", if not set to the first index
        if input is not None and any(d['name'] == input["name"] for d in input_devices):
            # print(f"Using saved input device index: {input}")
            pass
        else:
            input = input_devices[0] if input_devices else None
            self.settings["input_device"] = input

        #see if output device is in "devices", if not set to the first index
        if output is not None and any(d['name'] == output["name"] for d in output_devices):
            # print(f"Using saved output device index: {output}")
            pass
        else:
            output = output_devices[0] if output_devices else None
            self.settings["output_device"] = output

        if not "http_port" in self.settings:
            self.settings["http_port"] = 5010


        self.save_settings()
        

        
    
    def get_settings(self, name):
        # print(f"Getting setting '{name}': {self.settings}")
        return self.settings.get(name, None)

    def get_all_settings(self):
        return self.settings
    
    def set_settings(self, name, value):
        if(name not in self.settings):
            raise ValueError(f"Setting '{name}' not found.")
        self.settings[name] = value
        self.save_settings()
    
    def save_settings(self):
        self.refresh_settings()
        with open(self.settings_file, "w") as f:
            json.dump(self.settings, f, indent=4)

    def refresh_settings(self):
        recorder = AudioIO()
        # Update recorder parameters based on new setting
        recorder.set_buffer_duration(self.get_settings('recording_length'))
        recorder.recordings_dir = self.get_settings('save_path')
        
        audio_manager = WindowsAudioManager()
        audio_manager.set_default_input_device(self.get_settings('input_device'))
        audio_manager.set_default_output_device(self.get_settings('output_device'))

        recorder.refresh_streams()

