#!/usr/bin/python3

import configparser
import ruamel.yaml
import sys
import json
import re
import os
import time

SYSTEM_CONF_PATH=["/etc/speaker.conf", "/oem/etc/volctrl.conf", "/oem/etc/schedule.conf", "/oem/.record/firmware_url"]
TMPFILE="/tmp/conf"

origin_keys = {
    "system": [
        "firmware",
        "hard_version",
        "model",
        "ui_model"
    ],
    "account_info_p2p": [
        "transport",
        "allowanoymous"
    ],
    "secret": [
        "ui_username"
    ],
    "upgrade": [
        "reset_default",
        "date"
    ],
    "volume": [
        "hard_volume_control"
    ]
}

comment_data = {
    'system': {
        'system': {
            'cn': '系统设置.',
            'en': 'System Settings.'
        },
        'language': {
            'cn': '系统语音语言. 值：cn | en',
            'en': 'System voice language. Value: cn | en',
            'check': {
                'type': 'string',
                'empty': False,
                'method': 'enums',
                'data_enums': ['cn', 'en']
            }
        },
        'broadcast_service': {
            'cn': 'IP Audio Center服务开启. 值：yes | no',
            'en': 'Enable IP Audio Center Service. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'account_info_1': [
                            'server',
                            'port',
                            'username',
                            'authuser',
                            'reg_expires',
                            'transport',
                            'enable'
                        ]
                    }
                } 
            }
        },
        'ip_assign': {
            'cn': '系统IP获取方式. 值：static | dhcp',
            'en': 'System IP get mode. Value: static | dhcp',
            'check': {
                'type': 'string',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'static': {
                        'system': [
                            'ipaddr',
                            'netmask',
                            'gateway',
                            'dns1'
                        ]
                    }
                },
                'method': 'enums',
                'data_enums': ['static', 'dhcp']
            }
        },
        'ipaddr': {
            'cn': '系统IP地址. 例: 192.168.1.100',
            'en': 'System IP address. el: 192.168.1.100',
            'check': {
                'type': 'string',
                'method': 'regex_ip'
            }
        },
        'netmask': {
            'cn': '子网掩码. 例：255.255.255.0',
            'en': 'Subnet mask. el: 255.255.255.0',
            'check': {
                'type': 'string',
                'method': 'regex_ip'
            }
        },
        'gateway': {
            'cn': '系统网络网关地址 例：192.168.1.1',
            'en': 'System gateway ip address. el: 192.168.1.1',
            'check': {
                'type': 'string',
                'method': 'regex_ip'
            }
        },
        'dns1': {
            'cn': '系统主dns地址. 例: 114.114.114.114',
            'en': 'System Primary DNS address. el: 114.114.114.114',
            'check': {
                'type': 'string',
                'method': 'regex_ip'
            }
        },
        'dns2': {
            'cn': '系统备dns地址. 例: 8.8.8.8',
            'en': 'System Alternative DNS address. el: 8.8.8.8',
            'check': {
                'type': 'string',
                'method': 'regex_ip'
            }
        },
        'enable_ntp': {
            'cn': '启动NTP服务(系统自动获取网络时间) 值：yes | no',
            'en': 'Enanle NTP service(Auto get system time from network). Vlaue: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'system': [
                            'ntpserver',
                            'timezone',
                            'tzname'
                        ]
                    }
                }
            }
        },
        'ntpserver': {
            'cn': 'NTP服务器地址. 例: pool.ntp.org',
            'en': 'NTP server address. el: pool.ntp.org',
            'check': {
                'type': 'string',
                'method': 'regex_domain'
            }
        },
        'timezone': {
            'cn': '系统时区 例: CST-8',
            'en': 'System time zone. el: CST-8',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'tzname': {
            'cn': '系统时区名 例: Asia/Chongqing',
            'en': 'System time zone name. el: Asia/chongqing',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'location': {
            'cn': '系统备注信息 例: Confrence intercom',
            'en': 'System mark information. el: Confrence intercom',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'access_type': {
            'cn': 'WEB UI访问协议 值:0 | 1 | 2. 例: 1 (http)',
            'en': 'WEB UI access protocol. Value: 0 | 1 | 2. el: 1 (http)',
            'check': {
                'type': 'string',
                'empty': False,
                'method': 'enums',
                'data_enums': ['0', '1', '2']
            }
        },
        'route': {
            'cn': '系统默认路由 值:local | pppoe. 例: local',
            'en': 'System default route. Value: local | pppoe. el: pppoe',
            'check': {
                'type': 'string',
                'empty': False,
                'method': 'enums',
                'data_enums': ['local', 'pppoe']
            }
        }
    },
    'account_info_1': {
        'account_info_1': {
            'cn': '主SIP账号配置.',
            'en': 'Primary SIP Account Settings.'
        },
        'server': {
            'cn': 'SIP服务器地址.',
            'en': 'SIP server address.',
            'check': {
                'type': 'string',
                'method': 'regex_domain'
            }
        },
        'port': {
            'cn': 'SIP服务器端口. 范围: 1 - 65535. 例: 5060',
            'en': 'System server port. range: 1 - 65535. el: 5060',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'username': {
            'cn': 'SIP用户名.',
            'en': 'SIP username.',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'authuser': {
            'cn': 'SIP认证用户.',
            'en': 'SIP Auth user.',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'passwd': {
            'cn': 'SIP账号密码.',
            'en': 'SIP account password.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'enable': {
            'cn': '启用此SIP账号. 值: yes | no',
            'en': 'Enable SIP account. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'account_info_1': [
                            'server',
                            'port',
                            'username',
                            'authuser',
                            'reg_expires',
                            'transport'
                        ]
                    }
                } 
            }
        },
        'reg_expires': {
            'cn': '注册过期时间(秒). 范围: 1 - 3600. 例: 180',
            'en': 'Register expires(Seconds). range: 1 - 3600. el: 180',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 3600
                }
            }
        },
        'transport': {
            'cn': '网络传输协议. 值: udp | tcp | tls',
            'en': 'Network transmission protocol. Value: udp | tcp | tls',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': ['udp', 'tcp', 'tls']
            }
        },
        'autoanswer': {
            'cn': '自动接听. 值：yes | no | 10 (延迟10秒应答)',
            'en': 'Auto Answer. Value: yes | no | 10 (delay 10 Seconds answer)',
            'check': {
                'type': 'string',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {},
                    'no': {
                        'account_info_1': [
                            'ringfile'
                        ]
                    },
                    'default': {
                        'account_info_1': [
                            'ringfile'
                        ]
                    }
                },
                'method': 'default'
            }
        },
        'ringfile': {
            'cn': '来电铃声. 例: sweet.wav',
            'en': 'Ring. el: sweet.wav',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'alarm_tone0.wav',
                    'alarm_tone1.wav',
                    'alarm_tone2.wav',
                    'bell_burglar_ring.wav',
                    'bells_music_tone.wav',
                    'bigben.wav',
                    'digital_telephone.wav',
                    'emergency_alarm_tone.wav',
                    'emergency_beep_tone.wav',
                    'oldphone.wav',
                    'ring.wav',
                    'special_music_tone.wav',
                    'sweet.wav',
                    'toy.wav',
                    '1.wav',
                    '2.wav',
                    '3.wav',
                    '4.wav',
                    '5.wav'
                ]
            }
        },
        'nat_mode': {
            'cn': 'NAT模式. 值: disabled | stun | turn | ice',
            'en': 'NAT Mode. Value: disabled | stun | turn | ice',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'disabled',
                    'stun',
                    'turn',
                    'ice'
                ]
            }
        },
        'stun_server': {
            'cn': '服务器地址.',
            'en': 'Server address.',
            'check': {
                'type': 'string',
                'method': 'regex_domain'
            }
        },
        'stun_port': {
            'cn': '服务器端口. 范围: 1 - 65535. 例: 3478',
            'en': 'Server port. range: 1 - 65535. el: 3478',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'nat_username': {
            'cn': 'NAT用户名.',
            'en': 'NAT username.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'nat_password': {
            'cn': 'NAT账号密码.',
            'en': 'NAT account password.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        }
    },
    'account_info_2': {
        'account_info_2': {
            'cn': '备SIP账号1配置.',
            'en': 'Secondary SIP Account-1 Settings.'
        },
        'server': {
            'cn': 'SIP服务器地址.',
            'en': 'SIP server address.',
            'check': {
                'type': 'string',
                'method': 'regex_domain'
            }
        },
        'port': {
            'cn': 'SIP服务器端口. 范围: 1 - 65535. 例: 5060',
            'en': 'System server port. range: 1 - 65535. el: 5060',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'username': {
            'cn': 'SIP用户名.',
            'en': 'SIP username.',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'authuser': {
            'cn': 'SIP认证用户.',
            'en': 'SIP Auth user.',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'passwd': {
            'cn': 'SIP账号密码.',
            'en': 'SIP account password.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'enable': {
            'cn': '启用此SIP账号. 值: yes | no',
            'en': 'Enable SIP account. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'account_info_2': [
                            'server',
                            'port',
                            'username',
                            'authuser',
                            'reg_expires',
                            'transport'
                        ]
                    }
                }
            }
        },
        'reg_expires': {
            'cn': '注册过期时间(秒). 范围: 1 - 3600. 例: 180',
            'en': 'Register expires(Seconds). range: 1 - 3600. el: 180',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 3600
                }
            }
        },
        'transport': {
            'cn': '网络传输协议. 值: udp | tcp | tls',
            'en': 'Network transmission protocol. Value: udp | tcp | tls',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': ['udp', 'tcp', 'tls']
            }
        },
        'autoanswer': {
            'cn': '自动接听. 值：yes | no | 10 (延迟10秒应答)',
            'en': 'Auto Answer. Value: yes | no | 10 (delay 10 Seconds answer)',
            'check': {
                'type': 'string',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {},
                    'no': {
                        'account_info_2': [
                            'ringfile'
                        ]
                    },
                    'default': {
                        'account_info_2': [
                            'ringfile'
                        ]
                    }
                },
                'method': 'default'
            }
        },
        'ringfile': {
            'cn': '来电铃声. 例: sweet.wav',
            'en': 'Ring. el: sweet.wav',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'alarm_tone0.wav',
                    'alarm_tone1.wav',
                    'alarm_tone2.wav',
                    'bell_burglar_ring.wav',
                    'bells_music_tone.wav',
                    'bigben.wav',
                    'digital_telephone.wav',
                    'emergency_alarm_tone.wav',
                    'emergency_beep_tone.wav',
                    'oldphone.wav',
                    'ring.wav',
                    'special_music_tone.wav',
                    'sweet.wav',
                    'toy.wav',
                    '1.wav',
                    '2.wav',
                    '3.wav',
                    '4.wav',
                    '5.wav'
                ]
            }
        },
        'nat_mode': {
            'cn': 'NAT模式. 值: disabled | stun | turn | ice',
            'en': 'NAT Mode. Value: disabled | stun | turn | ice',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'disabled',
                    'stun',
                    'turn',
                    'ice'
                ]
            }
        },
        'stun_server': {
            'cn': '服务器地址.',
            'en': 'Server address.',
            'check': {
                'type': 'string',
                'method': 'regex_domain'
            }
        },
        'stun_port': {
            'cn': '服务器端口. 范围: 1 - 65535. 例: 3478',
            'en': 'Server port. range: 1 - 65535. el: 3478',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'nat_username': {
            'cn': 'NAT用户名.',
            'en': 'NAT username.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'nat_password': {
            'cn': 'NAT账号密码.',
            'en': 'NAT account password.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        }
    },
    'account_info_3': {
        'account_info_3': {
            'cn': '备SIP账号2配置.',
            'en': 'Secondary SIP Account-2 Settings.'
        },
        'server': {
            'cn': 'SIP服务器地址.',
            'en': 'SIP server address.',
            'check': {
                'type': 'string',
                'method': 'regex_domain'
            }
        },
        'port': {
            'cn': 'SIP服务器端口. 范围: 1 - 65535. 例: 5060',
            'en': 'System server port. range: 1 - 65535. el: 5060',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'username': {
            'cn': 'SIP用户名.',
            'en': 'SIP username.',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'authuser': {
            'cn': 'SIP认证用户.',
            'en': 'SIP Auth user.',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'passwd': {
            'cn': 'SIP账号密码.',
            'en': 'SIP account password.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'enable': {
            'cn': '启用此SIP账号. 值: yes | no',
            'en': 'Enable SIP account. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'account_info_3': [
                            'server',
                            'port',
                            'username',
                            'authuser',
                            'reg_expires',
                            'transport'
                        ]
                    }
                }
            }
        },
        'reg_expires': {
            'cn': '注册过期时间(秒). 范围: 1 - 3600. 例: 180',
            'en': 'Register expires(Seconds). range: 1 - 3600. el: 180',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 3600
                }
            }
        },
        'transport': {
            'cn': '网络传输协议. 值: udp | tcp | tls',
            'en': 'Network transmission protocol. Value: udp | tcp | tls',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': ['udp', 'tcp', 'tls']
            }
        },
        'autoanswer': {
            'cn': '自动接听. 值：yes | no | 10 (延迟10秒应答)',
            'en': 'Auto Answer. Value: yes | no | 10 (delay 10 Seconds answer)',
            'check': {
                'type': 'string',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {},
                    'no': {
                        'account_info_3': [
                            'ringfile'
                        ]
                    },
                    'default': {
                        'account_info_3': [
                            'ringfile'
                        ]
                    }
                },
                'method': 'default'
            }
        },
        'ringfile': {
            'cn': '来电铃声. 例: sweet.wav',
            'en': 'Ring. el: sweet.wav',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'alarm_tone0.wav',
                    'alarm_tone1.wav',
                    'alarm_tone2.wav',
                    'bell_burglar_ring.wav',
                    'bells_music_tone.wav',
                    'bigben.wav',
                    'digital_telephone.wav',
                    'emergency_alarm_tone.wav',
                    'emergency_beep_tone.wav',
                    'oldphone.wav',
                    'ring.wav',
                    'special_music_tone.wav',
                    'sweet.wav',
                    'toy.wav',
                    '1.wav',
                    '2.wav',
                    '3.wav',
                    '4.wav',
                    '5.wav'
                ]
            }
        },
        'nat_mode': {
            'cn': 'NAT模式. 值: disabled | stun | turn | ice',
            'en': 'NAT Mode. Value: disabled | stun | turn | ice',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'disabled',
                    'stun',
                    'turn',
                    'ice'
                ]
            }
        },
        'stun_server': {
            'cn': '服务器地址.',
            'en': 'Server address.',
            'check': {
                'type': 'string',
                'method': 'regex_domain'
            }
        },
        'stun_port': {
            'cn': '服务器端口. 范围: 1 - 65535. 例: 3478',
            'en': 'Server port. range: 1 - 65535. el: 3478',
            'check': {
                'type': 'int',
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'nat_username': {
            'cn': 'NAT用户名.',
            'en': 'NAT username.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'nat_password': {
            'cn': 'NAT账号密码.',
            'en': 'NAT account password.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        }
    },
    'account_info_p2p': {
        'account_info_p2p': {
            'cn': 'P2P账号配置.',
            'en': 'P2P account settings.'
        },
        'username': {
            'cn': 'p2p账号. 例: 1001',
            'en': 'p2p account. el: 1001',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'enable': {
            'cn': '启动p2p账号. 值：yes | no',
            'en': 'Enable p2p account. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'account_info_p2p': [
                            'username',
                        ]
                    }
                }
            }
        },
        'autoanswer': {
            'cn': '自动接听. 值：yes | no | 10 (延迟10秒应答)',
            'en': 'Auto Answer. Value: yes | no | 10 (delay 10 Seconds answer)',
            'check': {
                'type': 'string',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {},
                    'no': {
                        'account_info_p2p': [
                            'ringfile'
                        ]
                    },
                    'default': {
                        'account_info_p2p': [
                            'ringfile'
                        ]
                    }
                },
                'method': 'default'
            }
        },
        'ringfile': {
            'cn': '来电铃声. 例: sweet.wav',
            'en': 'Ring. el: sweet.wav',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'alarm_tone0.wav',
                    'alarm_tone1.wav',
                    'alarm_tone2.wav',
                    'bell_burglar_ring.wav',
                    'bells_music_tone.wav',
                    'bigben.wav',
                    'digital_telephone.wav',
                    'emergency_alarm_tone.wav',
                    'emergency_beep_tone.wav',
                    'oldphone.wav',
                    'ring.wav',
                    'special_music_tone.wav',
                    'sweet.wav',
                    'toy.wav',
                    '1.wav',
                    '2.wav',
                    '3.wav',
                    '4.wav',
                    '5.wav'
                ]
            }
        }
    },
    'sip_advance': {
        'sip_advance': {
            'cn': 'SIP高级设置.',
            'en': 'Advance SIP Settings.'
        },
        'localport': {
            'cn': 'SIP本地端口. 范围: 1 - 65535. 例: 5060',
            'en': 'System local port. range: 1 - 65535. el: 5060',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'rtpstartport': {
            'cn': 'RTP开始端口. 范围: 1 - 65535. 例: 5060',
            'en': 'RTP start port. range: 1 - 65535. el: 5060',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'rtpendport': {
            'cn': 'RTP结束端口. 范围: 1 - 65535. 例: 5060',
            'en': 'RTP end port. range: 1 - 65535. el: 5060',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 65535
                }
            }
        },
        'rtptimeout': {
            'cn': 'RTP超时时间(秒). 范围: 1 - 3600. 例: 60',
            'en': 'RTP timeout(Seconds) range: 1 - 3600. el: 60',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 3600
                }
            }
        }
    },
    'codec': {
        'codec': {
            'cn': '音频编码设置.',
            'en': 'Audio Codecs Settings.'
        },
        'g722': {
            'cn': '开启G722编码. 值: yes | no',
            'en': 'Enable G722 codec. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'alaw': {
            'cn': '开启G711(alaw)编码. 值: yes | no',
            'en': 'Enable G711(alaw) codec. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'ulaw': {
            'cn': '开启G711(ulaw)编码. 值: yes | no',
            'en': 'Enable G711(ulaw) codec. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'opus': {
            'cn': '开启OPUS编码. 值: yes | no',
            'en': 'Enable OPUS codec. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        }
    },
    'intercom': {
        'intercom': {
            'cn': '对讲及拨号设置.',
            'en': 'Press to talk Settings.'
        },
        'onekey_num': {
            'cn': '一键对讲号码. 例: 101',
            'en': 'One-key intercom number. el: 101',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'onekey_1_num': {
            'cn': '一键对讲号码 1. 例: 101',
            'en': 'One-key intercom number 1. el: 101',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'onekey_2_num': {
            'cn': '一键对讲号码 2. 例: 102',
            'en': 'One-key intercom number 2. el: 102',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'onekey_line': {
            'cn': '一键呼出线路. 值: auto | account_info_1 | account_info_2 | account_info_3 | p2p',
            'en': 'One-key outgoing line. Value: auto | account_info_1 | account_info_2 | account_info_3 | p2p',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'auto',
                    'account_info_1',
                    'account_info_2',
                    'account_info_3',
                    'p2p'
                ]
            }
        },
        'onekey_1_line': {
            'cn': '号码1呼出线路. 值: auto | account_info_1 | account_info_2 | account_info_3 | p2p',
            'en': 'One-key outgoing line. Value: auto | account_info_1 | account_info_2 | account_info_3 | p2p',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'auto',
                    'account_info_1',
                    'account_info_2',
                    'account_info_3',
                    'p2p'
                ]
            }
        },
        'onekey_2_line': {
            'cn': '号码2呼出线路. 值: auto | account_info_1 | account_info_2 | account_info_3 | p2p',
            'en': 'One-key outgoing line. Value: auto | account_info_1 | account_info_2 | account_info_3 | p2p',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'auto',
                    'account_info_1',
                    'account_info_2',
                    'account_info_3',
                    'p2p'
                ]
            }
        },
        'repress_cancel': {
            'cn': '再次按键取消呼叫. 值：yes | no',
            'en': 'Press again to cancel the call. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        }
    },
    'input_detect': {
        'input_detect': {
            'cn': '输入口设置.',
            'en': 'Sensor Settings.'
        },
        'enable': {
            'cn': '启动输入检测. 值：yes | no',
            'en': 'Enable input check. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'input_detect': [
                            'level'
                        ]
                    }
                }
            }
        },
        'level': {
            'cn': '触发模式(上升沿触发或下降沿触发). 值：low | high',
            'en': 'Trigger mode (rising edge trigger or falling edge trigger). Value: cn | en',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': ['low', 'high']
            }
        },
        'trigger_dial_enable': {
            'cn': '启动触发拨号 值：yes | no',
            'en': 'Enable trigger dial. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'input_detect': [
                            'trigger_num'
                        ]
                    }
                }
            }
        },
        'trigger_num': {
            'cn': '触发拨号的目的号码 例: 101',
            'en': 'The destination number that triggers the dialing. el: 101',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'trigger_line': {
            'cn': '呼出线路. 值: auto | account_info_1 | account_info_2 | account_info_3 | p2p',
            'en': 'Outgoing line. Value: auto | account_info_1 | account_info_2 | account_info_3 | p2p',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'auto',
                    'account_info_1',
                    'account_info_2',
                    'account_info_3',
                    'p2p'
                ]
            }
        }
    },
    'output': {
        'output': {
            'cn': '输出口设置.',
            'en': 'Relay Control Settings.'
        },
        'mode': {
            'cn': '触发模式. 值: delay | hangup | answered',
            'en': 'Trigger mode. Value: delay | hangup | answered',
            'check': {
                'type': 'string',
                'empty': False,
                'method': 'enums',
                'data_enums': ['delay', 'hangup', 'answered']
            }
        },
        'duration': {
            'cn': '持续时间(秒). 范围: 1 - 600 例: 10',
            'en': 'Duration(Seconds). range: 1 - 600 el: 10',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 1,
                    'end': 600
                }
            }
        },
        'type': {
            'cn': '触发类型. 值: On | FastFlashing | SlowFlashing',
            'en': 'Trigger type. Value: On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'empty': False,
                'method': 'enums',
                'data_enums': ['On', 'FastFlashing', 'SlowFlashing']
            }
        }
    },
    'trigger': {
        'trigger': {
            'cn': '触发设置.',
            'en': 'Trigger Settings.'
        },
        'input': {
            'cn': '启动输入触发. 值: yes | no',
            'en': 'Enable input trigger. Value: yes | no',
            'check': {
                'type': 'string',
                'empty': False,
            }
        },
        'dtmf': {
            'cn': '启动DTMF触发. 值: yes | no',
            'en': 'Enable DTMF trigger. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'trigger': [
                            'dtmf_code'
                        ]
                    }
                }
            }
        },
        'dtmf_code': {
            'cn': 'DTMF触发特征码. 例: 1*',
            'en': 'DTMF trigger feature code. Value: 1*',
            'check': {
                'type': 'string',
                'method': 'regex_dtmf'
            }
        },
        'call_state': {
            'cn': '启动通话状态触发. 值: yes | no',
            'en': 'Enable Call State trigger. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'trigger': [
                            'state_info'
                        ]
                    }
                }
            }
        },
        'state_info': {
            'cn': '设定触发的通话状态. 值: outgoing | incoming | hangup | both | answered',
            'en': 'Set the triggered call status. Value: outgoing | incoming | hangup | both | answered',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'outgoing',
                    'incoming',
                    'hangup',
                    'both',
                    'answered'
                ]
            }
        }
    },
    'multicast_player': {
        'multicast_player': {
            'cn': '组播设置.',
            'en': 'Multicast Settings.'
        },
        'enable': {
            'cn': '启动主播监听. 值: yes | no',
            'en': 'Enable multicast. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'address1': {
            'cn': '组播地址1. 例: rtp://@239.168.12.1:2000',
            'en': 'Multicast address 1. el: rtp://@239.168.12.1:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name1': {
            'cn': '组播地址1名称. 例: Background-Music-1',
            'en': 'Multicast address 1 name. el: Background-Music-1',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio1': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        },
        'address2': {
            'cn': '组播地址2. 例: rtp://@239.168.12.2:2000',
            'en': 'Multicast address 2. el: rtp://@239.168.12.2:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name2': {
            'cn': '组播地址2名称. 例: Background-Music-2',
            'en': 'Multicast address 2 name. el: Background-Music-2',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio2': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        },
        'address3': {
            'cn': '组播地址3. 例: rtp://@239.168.12.3:2000',
            'en': 'Multicast address 3. el: rtp://@239.168.12.3:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name3': {
            'cn': '组播地址3名称. 例: Background-Music-3',
            'en': 'Multicast address 3 name. el: Background-Music-3',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio3': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        },
        'address4': {
            'cn': '组播地址4. 例: rtp://@239.168.12.4:2000',
            'en': 'Multicast address 4. el: rtp://@239.168.12.4:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name4': {
            'cn': '组播地址4名称. 例: Background-Music-4',
            'en': 'Multicast address 4 name. el: Background-Music-4',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio4': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        },
        'address5': {
            'cn': '组播地址5. 例: rtp://@239.168.12.5:2000',
            'en': 'Multicast address 5. el: rtp://@239.168.12.5:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name5': {
            'cn': '组播地址5名称. 例: Background-Music-5',
            'en': 'Multicast address 5 name. el: Background-Music-5',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio5': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        },
        'address6': {
            'cn': '组播地址6. 例: rtp://@239.168.12.6:2000',
            'en': 'Multicast address 6. el: rtp://@239.168.12.6:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name6': {
            'cn': '组播地址6名称. 例: Background-Music-6',
            'en': 'Multicast address 6 name. el: Background-Music-6',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio6': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        },
        'address7': {
            'cn': '组播地址7. 例: rtp://@239.168.12.7:2000',
            'en': 'Multicast address 7. el: rtp://@239.168.12.7:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name7': {
            'cn': '组播地址7名称. 例: Background-Music-7',
            'en': 'Multicast address 7 name. el: Background-Music-7',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio7': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        },
        'address8': {
            'cn': '组播地址8. 例: rtp://@239.168.12.8:2000',
            'en': 'Multicast address 8. el: rtp://@239.168.12.8:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name8': {
            'cn': '组播地址8名称. 例: Background-Music-8',
            'en': 'Multicast address 8 name. el: Background-Music-8',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio8': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        },
        'address9': {
            'cn': '组播地址9. 例: rtp://@239.168.12.9:2000',
            'en': 'Multicast address 9. el: rtp://@239.168.12.9:2000',
            'check': {
                'type': 'string',
                'method': 'regex_multicast'
            }
        },
        'name9': {
            'cn': '组播地址9名称. 例: Background-Music-9',
            'en': 'Multicast address 9 name. el: Background-Music-9',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'gpio9': {
            'cn': 'GPIO触发. 值: Disabled | On | FastFlashing | SlowFlashing',
            'en': 'GPIO Trigger. Value: Disabled | On | FastFlashing | SlowFlashing',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'Disabled',
                    'On',
                    'FastFlashing',
                    'SlowFlashing'
                ]
            }
        }
    },
    'secret': {
        'secret': {
            'cn': 'WEB密码设置.',
            'en': 'WEB password settings.'
        },
        'ui_password': {
            'cn': 'WEB UI密码. 例: jkcjsdksd',
            'en': 'WEB UI password. el: jkcjsdksd',
            'check': {
                'type': 'string',
                'empty': False,
                'method': 'default'
            }
        }
    },
    'ipc': {
        'ipc': {
            'cn': '视频设置.',
            'en': 'Video settings.'
        },
        'url': {
            'cn': '画面效果. 例: 0(清晰)',
            'en': 'Effect Controls. el: 0(Standard)',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'payload': {
            'cn': 'H.264载荷类型. 例: 99',
            'en': 'H.264 Payload Type. el: 99',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 96,
                    'end': 127 
                }
            }
        },
        'rtsp_access': {
            'cn': 'RTSP访问. 值: yes | no',
            'en': 'RTSP Access. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        }
    },
    'audio_collection': {
        'audio_collection': {
            'cn': '音源采集设置.',
            'en': 'Audio Collection settings.'
        },
        'enable': {
            'cn': '开启音源采集. 值: yes | no.',
            'en': 'Enable Collection. Value: yes | no.',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'audio_collection': [
                            'server',
                            'username',
                            'password',
                            'name'
                        ]
                    }
                }
            }
        },
        'server': {
            'cn': '服务器地址.',
            'en': 'Server address.',
            'check': {
                'type': 'string',
                'method': 'regex_domain'
            }
        },
        'username': {
            'cn': '用户名.',
            'en': 'Username.',
            'check': {
                'type': 'string',
                'method': 'regex_username'
            }
        },
        'password': {
            'cn': '密码.',
            'en': 'Password.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'name': {
            'cn': '音源名称.',
            'en': 'Source Name.',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        }
    },
    'volume': {
        'volume': {
            'cn': '系统音量设置.',
            'en': 'System volume settings.'
        },
        'agc': {
            'cn': 'MIC自动增益. 值: yes | no',
            'en': 'MIC automatic gain. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
                'relate': True,
                'data_relate': {
                    'yes': {
                        'volume': [
                            'agc_min_volume',
                            'agc_max_volume'
                        ]
                    }
                }
            }
        },
        'volume_in': {
            'cn': '麦克风音量. 范围: 0 - 9. el: 5',
            'en': 'Microphone volume. range: 0 - 9. el: 5',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 0,
                    'end': 9
                }
            }
        },
        'volume_out': {
            'cn': '扬声器音量. 范围: 0 - 9. el: 5',
            'en': 'Speaker volume. range: 0 - 9. el: 5',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 0,
                    'end': 9
                }
            }
        },
        'agc_min_volume': {
            'cn': '自动增益最小音量. 范围: 0 - 9. el: 2',
            'en': 'AGC Min Volume. range: 0 - 9. el: 2',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 0,
                    'end': 9
                }
            }
        },
        'agc_max_volume': {
            'cn': '自动增益最大音量. 范围: 0 - 9. el: 2',
            'en': 'AGC Max Volume. range: 0 - 9. el: 2',
            'check': {
                'type': 'int',
                'empty': False,
                'method': 'range',
                'range': {
                    'start': 0,
                    'end': 9
                }
            }
        },
        'key_beep': {
            'cn': '按键音启动. 值: yes | no',
            'en': 'Key beep enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        }
    },
    'auto_privisioning': {
        'auto_privisioning': {
            'cn': '自动配置设置.',
            'en': 'Auto Privisioning settings.'
        },
        'address': {
            'cn': '服务器地址. 例: 10.10.1.15 或 http://192.168.1.100/files/',
            'en': 'Server address. el: 10.10.1.15() or http://192.168.1.100/files/',
            'check': {
                'type': 'string',
                'method': 'default'
            }
        },
        'mode': {
            'cn': '访问模式. 值: tftp | http',
            'en': 'Access mode. Value: tftp | http',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'tftp',
                    'http'
                ]
            }
        },
        'format': {
            'cn': '配置文件格式. 值: json | yaml',
            'en': 'Configuration file format. Value: json | yaml',
            'check': {
                'type': 'string',
                'method': 'enums',
                'data_enums': [
                    'json',
                    'yaml'
                ]
            }
        }
    },
    'call_action_url': {
        'call_action_url': {
            'cn': '呼叫事件回调URL设置.',
            'en': 'Call event callback URL settings.'
        },
        'incoming_enable': {
            'cn': '呼入回调URL启动. 值: yes | no',
            'en': 'Incoming callback URL enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'incoming_url': {
            'cn': '呼入回调URL. el: http://192.168.1.100/incoming',
            'en': 'Incoming callback URL. el: http://192.168.1.100/incoming',
            'check': {
                'type': 'string',
                'method': 'default',
            }
        },
        'outgoing_enable': {
            'cn': '呼出回调URL启动. 值: yes | no',
            'en': 'Outgoing callback URL enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'outgoing_url': {
            'cn': '呼出回调URL. el: http://192.168.1.100/outgoing',
            'en': 'Outgoing callback URL. el: http://192.168.1.100/outgoing',
            'check': {
                'type': 'string',
                'method': 'default',
            }
        },
        'answered_enable': {
            'cn': '应答回调URL启动. 值: yes | no',
            'en': 'Answered callback URL enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'answered_url': {
            'cn': '应答回调URL. el: http://192.168.1.100/answered',
            'en': 'Answered callback URL. el: http://192.168.1.100/answered',
            'check': {
                'type': 'string',
                'method': 'default',
            }
        },
        'hangup_enable': {
            'cn': '挂断回调URL启动. 值: yes | no',
            'en': 'Hangup callback URL enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'hangup_url': {
            'cn': '挂断回调URL. el: http://192.168.1.100/hangup',
            'en': 'Hangup callback URL. el: http://192.168.1.100/hangup',
            'check': {
                'type': 'string',
                'method': 'default',
            }
        }
    },
    'relay_action_url': {
        'relay_action_url': {
            'cn': '继电器事件回调URL设置.',
            'en': 'Relay event callback URL settings.'
        },
        'on_enable': {
            'cn': '继电器开回调URL启动. 值: yes | no',
            'en': 'Relay on callback URL enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'on_url': {
            'cn': '继电器开回调URL. el: http://192.168.1.100/on',
            'en': 'Relay on callback URL. el: http://192.168.1.100/on',
            'check': {
                'type': 'string',
                'method': 'default',
            }
        },
        'off_enable': {
            'cn': '继电器关回调URL启动. 值: yes | no',
            'en': 'Relay off callback URL enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'off_url': {
            'cn': '继电器关回调URL. el: http://192.168.1.100/off',
            'en': 'Relay off callback URL. el: http://192.168.1.100/off',
            'check': {
                'type': 'string',
                'method': 'default',
            }
        }
    },
    'api': {
        'api': {
            'cn': 'API设置.',
            'en': 'API settings.'
        },
        'call_enable': {
            'cn': '呼叫API启动. 值: yes | no',
            'en': 'Call API enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'relay_enable': {
            'cn': '继电器API启动. 值: yes | no',
            'en': 'Relay API enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        },
        'player_enable': {
            'cn': '播放器API启动. 值: yes | no',
            'en': 'Player API enable. Value: yes | no',
            'check': {
                'type': 'bool',
                'empty': False,
            }
        }
    },
    'default': {
        'cn': '',
        'en': ''
    }
}

if not hasattr(ruamel.yaml.comments.CommentedMap, "yaml_set_comment_before_key"):
    def my_yaml_set_comment_before_key(self, key, comment, column=None,
                                       clear=False):
        """
        append comment to list of comment lines before key, '# ' is inserted
            before the comment
        column: determines indentation, if not specified take indentation from
                previous comment, otherwise defaults to 0
        clear: if True removes any existing comments instead of appending
        """
        key_comment = self.ca.items.setdefault(key, [None, [], None, None])
        if clear:
            key_comment[1] = []
        comment_list = key_comment[1]
        if comment:
            comment_start = '# '
            if comment[-1] == '\n':
                comment = comment[:-1]  # strip final newline if there
        else:
            comment_start = '#'
        if column is None:
            if comment_list:
                 # if there already are other comments get the column from them
                column = comment_list[-1].start_mark.column
            else:
                column = 0
        # start_mark = ruamel.yaml.error.CommentMark(None, None, None, column, None, None)
        start_mark = ruamel.yaml.error.CommentMark(column)
        comment_list.append(ruamel.yaml.tokens.CommentToken(
            comment_start + comment + '\n', start_mark, None))
        return self

    ruamel.yaml.comments.CommentedMap.yaml_set_comment_before_key = \
        my_yaml_set_comment_before_key

def deleteKeys(data = {}, keys = origin_keys):
    ret_data = data
    for key, value in keys.items():
        if key in ret_data:
            for k in value:
                if k in ret_data[key]:
                    del ret_data[key][k]
            if not ret_data[key]:
                del ret_data[key]
    return ret_data

def addComment(data, commentkeys = comment_data):
    tmp_data = data
    for key, value in tmp_data.items():
        try:
            if "cn" in commentkeys[key][key].keys() and "en" in commentkeys[key][key].keys():
                tmp_data.yaml_set_comment_before_key(key, commentkeys[key][key]["cn"], column=0)
                tmp_data.yaml_set_comment_before_key(key, commentkeys[key][key]["en"], column=0)
        except:
            tmp_data.yaml_set_comment_before_key(key, commentkeys['default']["cn"], column=0)
            # tmp_data.yaml_set_comment_before_key(key, commentkeys['default']["en"], column=0)

        cm = tmp_data[key]
        for k, v in value.items():
            try:
                if "cn" in commentkeys[key][k].keys() and "en" in commentkeys[key][k].keys():
                    cm.yaml_set_comment_before_key(k, commentkeys[key][k]["cn"], column=2)
                    cm.yaml_set_comment_before_key(k, commentkeys[key][k]["en"], column=2)
            except:
                cm.yaml_set_comment_before_key(k, commentkeys['default']["cn"], column=2)
                # cm.yaml_set_comment_before_key(k, commentkeys['default']["en"], column=2)
    return tmp_data

def exportIni2Yaml(src = SYSTEM_CONF_PATH, dest = TMPFILE):
    ini = configparser.RawConfigParser()
    ini.read(src, encoding='utf-8')
    if ini.has_section("firmware"):
        ini.remove_section("firmware")
    ini_data = ini._sections
    final_data = deleteKeys(ini_data)
    

    data = ruamel.yaml.round_trip_load(ruamel.yaml.round_trip_dump(final_data))
    final_data = addComment(data)
    with open(dest, 'wb') as f:
        ruamel.yaml.round_trip_dump(final_data, f, encoding='utf-8')

    os.system("/etc/scripts/action.sh set_yaml")

def exportIni2Json(src = SYSTEM_CONF_PATH, dest = TMPFILE):
    ini = configparser.RawConfigParser()
    ini.read(src, encoding='utf-8')
    if ini.has_section("firmware"):
        ini.remove_section("firmware")
    ini_data = ini._sections
    final_data = deleteKeys(ini_data)
    with open(dest, 'w', encoding='utf-8') as f:
        json.dump(final_data, f, indent=4)

def checkData(data, section, key, value, check):
    res = {}
    if check['type'] == 'string':
        if 'empty' not in check:
            if not value:
                return None
        else:
            if check['empty'] and not value:
                return None
        if check['method'] == 'enums':
            for enum in check['data_enums']:
                if enum == value:
                    return None
            
            res.setdefault("check", "%s.%s" % (section, key))
            return res 
        elif check['method'] == 'regex_ip':
            if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", value):
                return None
            else:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "irregular")
                return res
        elif check['method'] == 'regex_domain':
            if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)+([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])$", value):
                return None
            else:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "irregular")
                return res
        elif check['method'] == 'regex_username':
            if re.match(r"^[a-zA-Z0-9.#@*][a-zA-Z0-9.#@*]{0,16}$", value):
                return None
            else:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "irregular")
                return res
        elif check['method'] == 'regex_dtmf':
            if re.match(r"^[0-9][0-9*]{0,16}$", value):
                return None
            else:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "irregular")
                return res
        elif check['method'] == 'regex_multicast':
            if re.match(r"rtp://@2(?:2[4-9]|3\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d?|0)){3}\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$", value):
                return None
            else:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "irregular")
                return res
        elif check['method'] == 'secret':
            if re.match(r"^[a-zA-Z]\w{4,16}$", value):
                return None
            else:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "irregular")
                return res
        else:
            pass

        if 'relate' in check and check['relate']:
            for m, n in check['data_relate'].items():
                if m == value:
                    if n:
                        for x, y in n.items():
                            for i in y:
                                if not data[x][i] or data[x][i] == '':
                                    res.setdefault("check", "%s.%s" % (x, i))
                                    # res.setdefault("status", "relate_irregular")
                                    return res
                            
                    return None
            try:
                number = float(value)
                
                if number <= 1 or number >= 3600:
                    res.setdefault("check", "%s.%s" % (section, key))
                    # res.setdefault("status", "relate_irregular")
                    return res
                for x, y in check['data_relate']['default'].items():
                    for i in y:
                        if data[x][i] == '' or not data[x][i]:
                            res.setdefault("check", "%s.%s" % (x, i))
                            # res.setdefault("status", "relate_irregular")
                            return res
                    
                return None
            except:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "relate_irregular")
                return res
            return None
        
        return None

    elif check['type'] == 'int':
        if not value:
            return None
        try:
            if check['range']['start'] <= int(value) and check['range']['end'] >= int(value):
                return None
            else:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "irregular")
                return res
        except:
                res.setdefault("check", "%s.%s" % (section, key))
                # res.setdefault("status", "irregular")
                return res
    elif check['type'] == 'bool':
        if 'empty' not in check:
            if not value:
                return None
        else:
            if check['empty'] and not value:
                return None
        if value == 'yes' or value == 'no':
            if 'relate' in check and check['relate']:
                for m, n in check['data_relate'].items():
                    if m == value:
                        if n:
                            for x, y in n.items():
                                for i in y:
                                    if not data[x][i] or data[x][i] == '':
                                        res.setdefault("check", "%s.%s" % (x, i))
                                        # res.setdefault("status", "relate_irregular")
                                        return res
                                
                        return None
            return None
        else:
            res.setdefault("check", "%s.%s" % (section, key))
            # res.setdefault("status", "relate_irregular")
            return res
    else:
        return None

def output_str(res):
    target = {}
    if "check" in res:
        target.setdefault("check", res["check"])
    else:
        target.setdefault("check", "unknown")

    return json.dumps(target)

def handleFirmwareUrl(url):
    if not url:
        return

    config_firmware = configparser.RawConfigParser()
    config_firmware.read(SYSTEM_CONF_PATH[3])
    old_url = config_firmware.get("firmware", "url")

    if url == old_url:
        return
    else:
        config_firmware.set("firmware", "url", url)
        with open(SYSTEM_CONF_PATH[3], 'w') as f:
            config_firmware.write(f, space_around_delimiters=False)
        
        config_system = configparser.RawConfigParser()
        config_system.read(SYSTEM_CONF_PATH[0])
        config_system.set("upgrade", "date", time.strftime("%Y-%m-%d"))
        with open(SYSTEM_CONF_PATH[0], 'w') as f:
            config_system.write(f, space_around_delimiters=False)

        os.system("/etc/scripts/onvif_upgrade.sh upgrade %s no" % url)

def importConfig(src = TMPFILE, dest = SYSTEM_CONF_PATH):
    try:
        with open(src, 'r', encoding='utf-8') as f:
            data = json.loads(f.read())
    except FileNotFoundError:
        res = {}
        res.setdefault("check", "file_not_found")
        print(output_str(res))
        sys.exit(0)
    except:
        try:
            with open(src, 'rb') as f:
                yaml=ruamel.yaml.YAML(typ='safe')
                data = yaml.load(f)
        except:
            res = {}
            res.setdefault("check", "file_format_error")
            print(output_str(res))
            os.remove(src)
            sys.exit(0)
    
    if type(data) != dict:
        res = {}
        res.setdefault("check", "file_format_error")
        print(output_str(res))
        os.remove(src)
        sys.exit(0) 
    
    output_data = deleteKeys(data)
    
    for key, value in output_data.items():
        for k, v in value.items():
            # try:
            #     res = checkData(output_data, key, k, v, comment_data[key][k]['check'])
            #     if res:
            #         print(output_str(res))
            #         os.remove(TMPFILE)
            #         sys.exit(0)
            # except SystemExit:
            #     sys.exit(0)
            # except KeyError:
            #     continue
            
            if not v:
                output_data[key][k] = ''
    
    if "volume" in output_data:
        volume_data = {}
        volume_data.setdefault("volume", output_data["volume"])
        del output_data["volume"]

        if "priority" in output_data:
            volume_data.setdefault("priority", output_data["priority"])
            del output_data["priority"]

        config_volume = configparser.RawConfigParser()
        config_volume.read(dest[1], encoding='utf-8')
        config_volume.read_dict(volume_data)

        with open(dest[1], 'w', encoding='utf-8') as f:
            config_volume.write(f, space_around_delimiters=False)
    
    if "schedule_1" in output_data:
        schedule_data = {}
        for i in range(1, 31):
            test_section="schedule_"+str(i)
            if test_section in output_data:
                schedule_data.setdefault(test_section, output_data[test_section])
                del output_data[test_section]

        if "holidays" in output_data:
            schedule_data.setdefault("holidays", output_data["holidays"])
            del output_data["holidays"] 
        
        if "screen_preset" in output_data:
            schedule_data.setdefault("screen_preset", output_data["screen_preset"])
            del output_data["screen_preset"]
        
        if "call_screen" in output_data:
            schedule_data.setdefault("call_screen", output_data["call_screen"])
            del output_data["call_screen"]
        
        config_schedule = configparser.RawConfigParser()
        config_schedule.read(dest[2], encoding='utf-8')
        config_schedule.read_dict(schedule_data)

        with open(dest[2], 'w', encoding='utf-8') as f:
            config_schedule.write(f, space_around_delimiters=False)

    
    config_system = configparser.RawConfigParser()
    config_system.read(dest[0], encoding='utf-8')
    config_system.read_dict(output_data)

    with open(dest[0], 'w', encoding='utf-8') as f:
        config_system.write(f, space_around_delimiters=False)

    if "firmware" in data and "url" in data["firmware"] and data["firmware"]["url"]:
        handleFirmwareUrl(data["firmware"]["url"])

    

if __name__ == "__main__":
    if len(sys.argv) == 2:
        action=sys.argv[1]
    else:
        res = {}
        res.setdefault("check", "Usage: %s export_yaml | export_json | import" % (sys.argv[0]))
        print(output_str(res))
        sys.exit(0)
    
    if action == 'export_yaml':
        exportIni2Yaml()
    elif action == 'export_json':
        exportIni2Json()
    elif action == 'import':
        importConfig()
        os.remove(TMPFILE)
    else:
        res = {}
        res.setdefault("check", "not_support_action")
        print(output_str(res))

    sys.exit(0)