
    
from dataclasses import dataclass
from typing import Any, Dict

from qlsdk.core.utils import to_bytes
from qlsdk.lse.exception import EStimConfigError
from qlsdk.lse.type import WaveFormEnum


class ParadigmConfig(object):
    def __init__(self, time_stamp, pkg_id, channels, impedance):
        self.time_stamp = time_stamp
        self.pkg_id = pkg_id
        self.channels = channels
        self.impedance = impedance
        
    def parse(json_data: Dict[str, Any]) -> 'ParadigmConfig':
        return ParadigmConfig(
            time_stamp=json_data.get("time_stamp"),
            pkg_id=json_data.get("pkg_id"),
            channels=json_data.get("channels"),
            impedance=json_data.get("impedance")
        )

@dataclass
class EStimConfig:
    # 刺激波形类型：0-正弦波，1-方波，2-三角波，3-特殊波形
    wave_form: int 
    # 电极通道-阳极
    anode_channels: list
    # 电极通道-阴极
    cathode_channels: list
    # 电流强度（单位：微安）
    current_intensity: int = 0
    # 是否伪刺激
    sham: bool = False
    # 延迟参数（单位：毫秒）
    delay_ms: int = 0
    # 延迟参数（单位：微秒）
    delay_us: int = 0
    # 刺激时长（单位：毫秒）
    stim_duration_ms: int = 0
    # 刺激上升时长（单位：毫秒）
    ramp_up_ms: int = 0
    # 刺激下降时长（单位：毫秒）
    ramp_down_ms: int = 0
    # 是否循环刺激
    loop: bool = False
    # 循环刺激次数
    loop_num: int = 1
    # 循环刺激间隔（单位：毫秒）
    loop_interval_ms: int = 0
    
    # 频率
    freq: float = None
    # 相位
    phase: int = None
    # 电流偏移量
    current_offset : int = None
    # 占空比-方波
    duty_cycle : int = None
    
    # 正向脉冲电流
    pos_current: int = None
    # 正向脉冲时间
    pos_pulse_us: int = None
    # 负向脉冲电流
    neg_current: int = None
    # 负向脉冲时间
    neg_pulse_us: int = None
    # 死区时间
    dead_us: int = None
    # 脉冲次数
    pulse_num: int = 1
    # 脉冲间隔
    pulse_interval_us: int = None
    
    # 随机种子，不能为0
    seed: float = 1
    # 高通截止频率1
    high_freq_1: int = None
    # 低通截止频率1
    low_freq_1: int = None
    # 高通截止频率2
    high_freq_2: int = None
    # 低通截止频率2
    low_freq_2: int = None
    
    _valid_wave_form = [wf.value for wf in WaveFormEnum]
        
    def __post_init__(self):  
        if self.wave_form not in self._valid_wave_form:
            raise EStimConfigError(f"无效的波形类型: {self.wave_form}")  
        
        if self.anode_channels is None or self.cathode_channels is None:
            raise EStimConfigError("电极通道不能为空")
        
        if len(self.anode_channels) == 0 or len(self.cathode_channels) == 0:
            raise EStimConfigError("电极通道必须为非负整数")
        
        if self.anode_channels == self.cathode_channels:
            raise EStimConfigError("正极和负极通道不能相同")
        
        # 当前可用通道数1、2、3、4，后续如果设备支持更多通道可以调整此处逻辑
        if len(self.anode_channels) > 4 or len(self.cathode_channels) > 4:
            raise EStimConfigError("电极通道编号不能超过4")
        
        if (self.delay_ms and self.delay_ms < -1) or (self.delay_us and self.delay_us < -1):
            raise EStimConfigError("延迟参数必须为非负整数")
        
        if self.stim_duration_ms is None or self.stim_duration_ms <= 0:
            raise EStimConfigError("刺激时长必须为正整数")
        
        if self.ramp_up_ms < 0 or self.ramp_down_ms < 0:
            raise EStimConfigError("上升/下降时长必须为非负整数")
        
        if self.loop and self.loop_num <= 0:
            raise EStimConfigError("循环刺激次数必须为正整数")
        
        if self.current_intensity is None or self.current_intensity < -25000 or self.current_intensity > 25000:
            raise EStimConfigError("电流强度应在-25000到25000之间")
        
    def to_json(self) -> Dict[str, Any]:
        
        # 通道-阳极
        pos_channels = int.from_bytes(to_bytes(self.anode_channels, 8), byteorder='big')
        # 通道-阴极
        neg_channels = int.from_bytes(to_bytes(self.cathode_channels, 8), byteorder='big')
        
        cfg = {
                "wType": self.wave_form,
                "PosCh": pos_channels,
                "NegCh": neg_channels,
                "IsSham": 1 if self.sham else 0,
                "sm_ms": self.ramp_up_ms,
                "du_ms": self.stim_duration_ms,
                "do_ms": self.ramp_down_ms,
                "isLoop": 1 if self.loop else 0,
                "lpCnt": self.loop_num,
                "lpIntvl": self.loop_interval_ms
            }
        
        if self.delay_ms and self.delay_ms >= 0:
            cfg["dy_ms"] = self.delay_ms
        
        if self.delay_us and self.delay_us >= 0:
            cfg["dy_us"] = self.delay_us   
            
        # 直流、非对称CES
        if  self.wave_form == WaveFormEnum.tDCS.value or self.wave_form == WaveFormEnum.nCES.value:   
            cfg["amp"] = self.current_intensity        
            return cfg
        
        # 方波、正弦波
        if  self.wave_form == WaveFormEnum.SQUARE.value or self.wave_form == WaveFormEnum.tACS.value: 
            cfg["amp"] = self.current_intensity         
            cfg["freq"] = self.freq
        
            if self.phase and self.phase >= 0:
                cfg["phase"] = self.phase
        
            if self.current_offset and self.current_offset >= 0:
                cfg["offset"] = self.current_offset   
            
            if self.wave_form == WaveFormEnum.SQUARE.value:
                cfg["dtyCyc"] = self.duty_cycle
                
            return cfg
        
        if self.wave_form == WaveFormEnum.RANDOM.value:
            cfg["Current"] = self.current_intensity
            cfg["hfp1"] = self.high_freq_1
            cfg["lfp1"] = self.low_freq_1
            
            if self.seed and self.seed > 0:
                cfg["seed"] = self.seed
            return cfg
            
        # 脉冲波形
        if  self.wave_form == WaveFormEnum.PULSE.value or  self.wave_form == WaveFormEnum.iTBS.value or self.wave_form == WaveFormEnum.cTBS.value:   
            #电流大小
            if self.pos_current is None:
                self.pos_current = abs(self.current_intensity)
            if self.neg_current is None:
                self.neg_current = -abs(self.current_intensity)
                
            cfg["Current"] = self.pos_current 
            cfg["Pulset"] = self.pos_pulse_us 
            cfg["nCurrent"] = self.neg_current
            cfg["nPulset"] = self.neg_pulse_us 
            cfg["Deadt"] = self.dead_us 
            cfg["RptCnt"] = self.pulse_num
            cfg["RptIntvl"] = self.pulse_interval_us
            cfg["WaveFreq"] = self.freq
            
                    
            return cfg
@dataclass            
class TACSConfig(EStimConfig):
    def __init__(self, freq: int, **kwargs):
        super().__init__(**kwargs)
        self.freq = freq
        
     # 重写父类的to_json方法，添加频率参数
    def to_json(self) -> Dict[str, Any]:
        base_json = super().to_json()
        base_json["freq"] = self.freq
        return base_json
    
@dataclass
class SquareWaveConfig(EStimConfig):
    def __init__(self, freq: int, **kwargs):
        super().__init__(**kwargs)
        self.freq = freq
        
     # 重写父类的to_json方法，添加频率参数
    def to_json(self) -> Dict[str, Any]:
        base_json = super().to_json()
        base_json["freq"] = self.freq
        return base_json   
@dataclass
class PulseConfig(EStimConfig):
        
     # 重写父类的to_json方法，添加频率参数
    def to_json(self) -> Dict[str, Any]:
        base_json = super().to_json()
        base_json["pulse_width_us"] = self.pulse_width_us
        return base_json    
        
@dataclass        
class LightSoundStimConfig:
    # 光照频率(Hz, 精度：0.1Hz，范围：[0-200])
    light_freq: float
    # 光照占空比(范围：[0-100])
    light_duty_cycle: float
    # 光照强度（lux, 范围：[0-8000])
    light_intensity: float
    # 声音频率(Hz, 精度：0.1Hz，范围：[0-200])
    sound_freq: float
    # 声音占空比(范围：[0-100])
    sound_duty_cycle: float
    # 光刺激启动延迟时间(单位：微秒，精度：1微秒)
    light_delay_us: int = -1
    # 声音刺激启动延迟时间(单位：微秒，精度：1微秒)
    sound_delay_us: int = -1
    # 音频名称
    audio_name: str = 'SIN_WAVE'
    # 音频音量（范围：[0-100])
    audio_volume: float= 30
    # 音频载波频率（仅audio_name=SIN_WAVE时有效，单位：Hz, 精度： 范围：200-10000）
    audio_carrier_freq: float = 10000
    # 持续时长（单位：秒， 精度: 0.001秒）
    duration: float = 0
        
    def to_json(self) -> Dict[str, Any]:
        cfg =  {
            "Audio": self.audio_name,
            "duration_s": self.duration,
            "Ach": 0,
            "Avolume": self.audio_volume,
            "Afreq": self.sound_freq,
            "Aduty": self.sound_duty_cycle,
            "Ady_us": self.sound_delay_us,
            "ABaseFreq": self.audio_carrier_freq,
            "ABaseAmp": 32767
        }    
        
        cfg['Lch'] = 0
        # 光强度
        if self.light_intensity:
            cfg['Lintensity'] = self.light_intensity
        if self.light_freq:
            cfg['Lfreq'] = self.light_freq
        if self.light_duty_cycle:
            cfg['Lduty'] = self.light_duty_cycle    
        if self.light_delay_us and self.light_delay_us > -1:
            cfg['Ldy_us'] = self.light_delay_us
        
        return cfg