# -*- coding:utf-8 -*-
"""Win ini格式的配置文件处理"""

from kyger.utility import url_absolute, str_replace
from configparser import ConfigParser


class Config(object):
    """
    处理 win ini 格式配置文件
    ini 文件允许备注，备注符号 # 前后不允许使用 TAB：
        val = 45  # 这里是备注
    """
    
    def __init__(self, file):
        """
        初始化
        :param file: ini 文件路径，相对于项目根目录的一个路径：/config/db.ini 或 config/db.ini 都行
        """
        self.ini_file = url_absolute(file)  # 转成绝对路径，否则 CMD 时报错
        self.cfg = ConfigParser(
            delimiters=(' = ', ': ', '=', ':', ' : ', '= '),  # keys 与 values之间的分隔符：a = 1 或 a: 1
            comment_prefixes=('#', ';'),  # 注释符
            strict=False,  # 是否严格解析，False 允许重复的 keys
        )
        self.cfg.read(self.ini_file, encoding="utf-8")
    
    def get(self, section=None, option=None):
        """
        获取 ini 配置文件，将 ini 文件转成 dict
        :param section: [str] 要获取的结点，为空时获取所有节点
        :param option: [str] 要获取的参数，为空时获取所有参数
        :return: str|dict 获取单个指定的参数时返回 str
        :Example: Config('config/db.ini').get('MySQLConfig', 'password')
        """
        r_config = {}
        section_list = [section] if section else self.cfg.sections()  # 节点列表
        for str_k in section_list:
            if not option:  # 获取所有参数
                config = {}
                for key, value in self.cfg.items(str_k):  # 所有配置信息
                    # 整形
                    value = self.note(value)  # 去掉备注
                    if value.isdigit(): value = int(value)  # 数字
                    elif value.capitalize() == 'True': value = True
                    elif value.capitalize() == 'False': value = False
    
                    # 合并
                    config.update({key: value})
                r_config.update({str_k: config})
            else:  # 获取指定的一个参数
                r_config = self.note(self.cfg.get(str_k, option))
        # 指定节点时返回该节点所有参数
        return r_config[section] if section and option is None else r_config
        
    def set(self, section, data={}):
        """
        设置 ini 参数，存在则修改、不存在则添加
        :param section: [str] 要设置的节点
        :param data: [dict] 要修改的参数，如：{'host': ('127.0.0.8', '服务器地址')}
        :return:
        :Example: Config('config/db.ini').set('MySQLConfig', {'a': (1, '备注信息'), 'b': 'True'})
        """
        for key, value in data.items():
            value = str(value) if not isinstance(value, tuple) else '%s  # %s' % (value[0], value[1])
            self.cfg.set(section, str(key), str_replace(value, "%", "%%"))  # 转义%，否则报错
        self.cfg.write(open(self.ini_file, "w", encoding="utf-8"), False)
        
    def remove(self, section, option=[]):
        """
        删除 ini 参数
        :param section: [str] 需要删除的节点，如果 option 为空时将删除整个节点
        :param option: [list|str] 需要删除的参数，为空时将删除整个节点
        :return:
        :Example: Config('config/db.ini').remove('MySQLConfig', ['a','host'])
        """
        if option:
            if not isinstance(option, list): option = [option]
            for key in option: self.cfg.remove_option(str(section), str(key))
        else:  # 删除整个节点
            self.cfg.remove_section(section)
        self.cfg.write(open(self.ini_file, "w", encoding="utf-8"), False)
        
    def note(self, row=''):
        """
        删除 # 后面的备注信息
        :param row: 要处理的字符串
        :return:
        """
        return row.split('# ')[0].strip()
