#!/usr/bin/python
# -*- coding: UTF-8 -*-
from plugins.DistributedStorage.utils.client.RestClient import RestClient
from plugins.DistributedStorage.utils.client.ResponseParse import ResponseParse
from utils.common.exception import HCCIException as HCCIException
import utils.common.log as logger
import traceback


def singleton_with_ip(cls):
    _instance = {}

    def _singleton(*args, **kargs):
        float_ip = args[0].get("float_ip")
        if float_ip not in _instance:
            _instance_node = dict()
            _instance_node[cls] = cls(*args, **kargs)
            _instance[float_ip] = _instance_node
        else:
            if cls not in _instance[float_ip]:
                _instance[float_ip][cls] = cls(*args, **kargs)
        return _instance[float_ip][cls]
    return _singleton


@singleton_with_ip
class UpgradeOperate(object):
    def __init__(self, fs_info):
        self.float_ip = fs_info.get("float_ip")
        self.port = fs_info.get("port", "8088")
        self.rest_client = RestClient(self.float_ip, self.port)
        self.sys_esn = None
        self.https = "https://"

    def try_login(self, username, password):
        ret_result, ret_data = self.get_session()
        logger.info("current session(%s, %s)" % (ret_result, ret_data))
        if not ret_result or ret_result["code"] != 0:
            return self.login(username, password)
        for resp in ret_data:
            if resp["status"] != '1':
                return self.login(username, password)
        return 200, 0, ""

    def login(self, username, password):
        res = []
        try:
            res = self.rest_client.login(username, password)
            result = ResponseParse(res)
            status_code, error_code, error_des = result.get_res_code()
            if status_code == 200 and error_code == 0:
                token = result.get_login_token()
                self.sys_esn = result.get_system_esn()
                self.rest_client.set_cookie(token)
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626301, str(e))
        return status_code, error_code, error_des

    def logout(self):
        uri = '/api/v2/aa/sessions?is_timeout=false'
        url = self.https + self.float_ip + ":" + self.port + uri
        try:
            res = self.rest_client.normal_request(url, 'delete')
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as exc:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            logger.error("logout failed, exc: {}".format(exc))
            return {"code": "-1"}, {}
        return ret_result, ret_data

    def get_session(self):
        uri = '/api/v2/aa/current_session'
        url = self.https + self.float_ip + ":" + self.port + uri
        res = []
        try:
            res = self.rest_client.normal_request(url, 'get')
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as exc:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            logger.error("get_session failed, exc: {}".format(exc))
            return {"code": "-1"}, {}
        return ret_result, ret_data

    def package_validaty(self, package_name, package_size):
        uri = "/api/v2/upgrade/upgrade_package_validaty"
        url = self.https + self.float_ip + ":" + self.port + uri
        data = {
            "package_name": package_name,
            "package_size": package_size
            }
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def set_upg_mode(self, mode="2"):
        uri = "/api/v2/upgrade/upgrade_mode"
        url = self.https + self.float_ip + ":" + self.port + uri
        data = {
            "upgrade_mode": mode
            }
        try:
            res = self.rest_client.normal_request(url, 'put', data)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def upload_upg_pkg(self, pkg_path):
        uri = "/api/v2/upgrade/upgrade_packages"
        url = self.https + self.float_ip + ":" + self.port + uri
        try:
            res = self.rest_client.upload_tar_request_stream(
                url, 'post', pkg_path)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def pre_check(self):
        uri = "/api/v2/upgrade/precheck"
        url = self.https + self.float_ip + ":" + self.port + uri
        data = {}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def get_pre_check_status(self):
        uri = "/api/v2/upgrade/precheck_status"
        url = self.https + self.float_ip + ":" + self.port + uri
        try:
            res = self.rest_client.normal_request(url, 'get')
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def upgrade_task(self):
        uri = "/api/v2/upgrade/upgrade_task"
        url = self.https + self.float_ip + ":" + self.port + uri
        data = {}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def get_upgrade_task(self):
        uri = "/api/v2/upgrade/task"
        url = self.https + self.float_ip + ":" + self.port + uri
        try:
            res = self.rest_client.normal_request(url, 'get')
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def get_upgrade_status(self):
        uri = "/api/v2/upgrade/upgrade_status"
        url = self.https + self.float_ip + ":" + self.port + uri
        try:
            res = self.rest_client.normal_request(url, 'get')
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def post_check(self):
        uri = "/api/v2/upgrade/postcheck"
        url = self.https + self.float_ip + ":" + self.port + uri
        data = {}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def get_post_check_result(self):
        uri = "/api/v2/deploy_manager/micro_service_postcheck_result"
        url = self.https + self.float_ip + ":" + self.port + uri
        try:
            res = self.rest_client.normal_request(url, 'get')
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def retry_upgrade_task(self):
        uri = "/api/v2/upgrade/upgrade_retry_task"
        url = self.https + self.float_ip + ":" + self.port + uri
        data = {}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def rollback_upgrade_task(self):
        uri = "/api/v2/upgrade/rollback_task"
        url = self.https + self.float_ip + ":" + self.port + uri
        data = {}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def upgrade_confirm(self):
        uri = "/api/v2/upgrade/upgrade_confirm"
        url = self.https + self.float_ip + ":" + self.port + uri
        data = {}
        try:
            res = self.rest_client.normal_request(url, 'post', data)
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def get_servers(self):
        uri = "/api/v2/cluster/servers"
        url = self.https + self.float_ip + ":" + self.port + uri
        try:
            res = self.rest_client.normal_request(url, 'get')
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data

    def get_product(self):
        uri = "/api/v2/cluster/product"
        url = self.https + self.float_ip + ":" + self.port + uri
        try:
            res = self.rest_client.normal_request(url, 'get')
            logger.info(res.json())
            result = ResponseParse(res)
            _, ret_result, ret_data = result.get_rsp_data()
        except Exception as e:
            logger.error(traceback.format_exc())
            logger.error(str(res))
            raise HCCIException(626304, str(e))
        return ret_result, ret_data
