#!/usr/bin/python3
# -*- coding: utf-8 -*-
import binascii
import gettext
import base64
import json
import os
import subprocess
from time import sleep
import dbus
import argparse
import logging
import socket
import errno


default_server = None  # 加域的服务器地址
default_username = None  # 加域账户名
default_password = None  # 加域账户密码
default_client_name = None  # 客户端主机名

# default_server = 'server.example.local'  # 加域的服务器地址
# default_username = 'domain-account'  # 加域账户名
# default_password = 'a3lsaW4xMjMuCg=='  # 加域账户密码
# default_client_name = 'client.example.local'  # 客户端主机名

# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------

default_password_encryption = False  # 当该值为True时,脚本会对账户密码进行解码操作
default_is_reboot_machine = False  # 当该值为True时,仅当加域成功后,重启机器


logger = logging.getLogger()
gettext.bindtextdomain('kim-domain', '/usr/share/kim-client/locale')
gettext.textdomain('kim-domain')
_ = gettext.gettext

requests.packages.urllib3.disable_warnings()
# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------

JOIN_ERR_UNKNOW = 100101                #未知错误
JOIN_ERR_NOTJOIN = 100102               #未加域
JOIN_ERR_CONFIG = 100103                #配置错误
JOIN_ERR_TIME_SKEW = 100104             #客户端与服务端时间相差过大
JOIN_ERR_RUN_NOPERM = 100105            #脚本需要root权限
JOIN_ERR_CLIENT_ERR = 100106            #客户端未安装或服务异常
JOIN_ERR_PARAM_ERR = 100107             #脚本参数错误
JOIN_ERR_ALREADY_JOIN = 100108          #已加域
JOIN_ERR_BACKEND = 100109               #后端错误

JOIN_ERR_NET_URL = 100201               #访问地址异常
JOIN_ERR_NET_TIMEOUT = 100202           #连接服务端超时
JOIN_ERR_NET_CONN = 100203              #连接网络异常
JOIN_ERR_NET_REQUEST = 100204           #请求错误
JOIN_ERR_NET_STATUS = 100205            #http请求状态码异常

JOIN_ERR_KCM = 100301                   #KCM调用错误

def out_put_err(err_code, err_msg):
    #with open('installmsg', 'w') as f:
    #    f.write('errcode = %d\n' % err_code)
    #    f.write('errmsg = %s\n' % err_msg)
    print('[%d]%s' % (err_code, err_msg))
    if err_code != 0 or err_code != 300000:
        exit(1)
    else:
        exit(0)

def out_msg(type, code, msg):
    if type == 'json':
        pass
    if type == 'line':
        print('[%d]%s' % (code, msg))
    if type == '':
        pass

def domain_status():
    dbus_object = dbus.SystemBus()
    service = dbus_object.get_object(
        "com.kylin.kim.domain", "/")
    interface = dbus.Interface(
        service, dbus_interface="com.kylin.kim.domain")
    status = interface.getDomainStatus()
    return status

def domain_join(args):
    server = args.server
    username = args.username
    password = args.password
    password_encryption = args.password_encryption
    is_reboot_machine = args.is_reboot_machine

    status = domain_status()
    if status != 0:
        return JOIN_ERR_ALREADY_JOIN, '终端已加域'

    client_name = args.client_name
    if client_name is None:
        client_name = socket.getfqdn()
    try:
        dbus_object = dbus.SystemBus()
        service = dbus_object.get_object(
            "com.kylin.kim.domain", "/")
        interface = dbus.Interface(
            service, dbus_interface="com.kylin.kim.domain")
    except dbus.exceptions.DBusException as error_message:
        return JOIN_ERR_CLIENT_ERR, '加域状态 : 请检查加域客户端软件包是否安装或其版本是否正确 (%s)' % error_message
    if password_encryption:
        try:
            password = str(base64.b64decode(
                password).decode()).replace('\n', '')
        except Exception as error_message:
            return JOIN_ERR_PARAM_ERR, ('加域状态 : 加域账号密码 解码错误，请检查密码是否正确 (%s)' % error_message)

    status, msg = interface.userJoinCommand(
        server, client_name, username, password)

    if status == 0:
        return 0, '加域状态 : 成功'
    else:
        return JOIN_ERR_BACKEND, "失败 (%s)" % msg


def domain_uninstall(args):
    server = args.server
    username = args.username
    password = args.password
    password_encryption = args.password_encryption

    if domain_status() == 0:
        return JOIN_ERR_NOTJOIN, '终端未加域'

    try:
        if password_encryption:
            password = str(base64.b64decode(
                password).decode()).replace('\n', '')

        dbus_object = dbus.SystemBus()
        service = dbus_object.get_object(
            "com.kylin.kim.domain", "/")
        interface = dbus.Interface(
            service, dbus_interface="com.kylin.kim.domain")
        ret, msg = interface.userAuthRemote(username, password)
        if ret != 0:
            return errno.EACCES, "退域认证失败：%s" % msg
        ret, msg = interface.unenroll()
        out_put_err(ret, msg)
        if ret != 0:
            return errno.EACCES, ("退域状态 : %s" % msg)
    except binascii.Error as error_message:
        return errno.EINVAL, ("退域状态 : 失败 (账号密码 解码错误，请检查密码是否正确 - %s)" % str(error_message))
    except Exception as error_message:
        return errno.EINVAL, ("退域状态 : 失败 (%s)" % str(error_message))

    return 0, ("退域状态 : 成功")

# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------


# 创建 ArgumentParser 对象
parser = argparse.ArgumentParser(
    description='Join domain Using the Command Line')

# 创建子命令解释器
subparsers = parser.add_subparsers(dest="command")  # dest: 子命令名称在命名空间中使用的键
sub_status = subparsers.add_parser('status')
# 添加子命令 'install'
sub_install = subparsers.add_parser('install')
# 添加子命令 'uninstall'
sub_uninstall = subparsers.add_parser('uninstall')
# 为 'install' 子命令创建参数组
group_install = sub_install.add_argument_group()
# 在参数组中添加参数
group_install.add_argument('--server', default=default_server, required=not default_server,
                           help='Server Domain Name/Address')
group_install.add_argument('--username', default=default_username, required=not default_username,
                           help='Add domain account')
group_install.add_argument('--password', default=default_password, required=not default_password,
                           help='Add domain account password')
group_install.add_argument('--client-name', default=default_client_name, required=False,
                           help='Client host name')

group_install.add_argument('--password-encryption', action='store_true', default=default_password_encryption,
                           help='Whether the password of the domain account is encrypted')
group_install.add_argument('--is-reboot-machine', action='store_true', default=default_is_reboot_machine,
                           help='Whether to restart the machine after the domain is successfully added')

# 为 'uninstall' 子命令创建参数组
group_uninstall = sub_uninstall.add_argument_group()

group_uninstall.add_argument('--server', required=False,
                             help='Server Domain Name/Address')
group_uninstall.add_argument('--username', required=True,
                             help='Add domain account')
group_uninstall.add_argument('--password', required=True,
                             help='Add domain account password')
group_uninstall.add_argument('--password-encryption', action='store_true',
                             help='Whether the password of the domain account is encrypted')


# 解析命令行参数
args = parser.parse_args()



if args.command == 'install':
    # 处理 'install' 子命令逻辑
    if os.geteuid() != 0:
        print("请使用管理员权限执行")
        out_put_err(JOIN_ERR_RUN_NOPERM, "请使用管理员权限执行")
        exit()
    is_reboot_machine = args.is_reboot_machine
    ret, msg = domain_join(args)

    print(msg)

    if ret == 0 and is_reboot_machine:
        try:
            print(
                "\033[033m系统将在十秒后重启, 按\033[031mCtrl + C\033[0m \033[033m取消.\033[0m")
            sleep(10)
            os.system("reboot")
        except KeyboardInterrupt:
            exit()
    exit(ret)

elif args.command == 'uninstall':
    # 处理 'uninstall' 子命令逻辑
    if os.geteuid() != 0:
        print("请使用管理员权限执行")
        out_put_err(JOIN_ERR_RUN_NOPERM, "请使用管理员权限执行")
        exit()
    ret, msg = domain_uninstall(args)
    print(msg)
    exit(ret)

elif args.command == 'status':
    try:
        status = domain_status()
        print(status)
        exit()
    except Exception as error_message:
        print("获取域状态 : 失败 (%s)" % str(error_message))
        exit(1)

else:
    # 如果没有指定子命令，则退出
    parser.print_help()
    #out_put_err(JOIN_ERR_PARAM_ERR, '参数错误')
    exit(-1)
