# -*- coding: utf-8 -*-
# !/usr/bin/env python

# Copyright (c) 2014 Baidu.com, Inc. All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

"""
This module provides a client class for LBDC.
"""
import copy
import json
import logging
import uuid

from baidubce.bce_base_client import BceBaseClient
from baidubce.auth import bce_v1_signer
from baidubce.http import bce_http_client
from baidubce.http import handler
from baidubce.http import http_methods

from baidubce import compat

_logger = logging.getLogger(__name__)


class LbdcClient(BceBaseClient):
    """

       LBDC base sdk client
    """

    prefix = b'/v1'
    path = b'/lbdc'

    def __init__(self, config=None):
        """
        :param config: client config info
        reuse BceBaseClient init func
        """
        BceBaseClient.__init__(self, config)

    @staticmethod
    def _generate_default_client_token():
        """

        default client token by uuid1
        """
        return uuid.uuid1()

    def _merge_config(self, config):
        """

        :type config: baidubce.BceClientConfiguration
        :param config:
        :return:
        """
        if config is None:
            return self.config
        else:
            new_config = copy.copy(self.config)
            new_config.merge_non_none_values(config)
            return new_config

    def _send_request(self, http_method, path, body=None, headers=None,
                      params=None, config=None, body_parser=None):
        """

        :param http_method:
        :param path:
        :param body:
        :param headers:
        :param params:

        :type config: baidubce.BceClientConfiguration
        :param config:

        :param body_parser:

        :return: baidubce.BceResponse
        """
        config = self._merge_config(config)
        if body_parser is None:
            body_parser = handler.parse_json

        if headers is None:
            headers = {b'Accept': b'*/*',
                       b'Content-Type': b'application/json;charset=utf-8'}

        return bce_http_client.send_request(config, bce_v1_signer.sign,
                                            [handler.parse_error, body_parser],
                                            http_method, LbdcClient.prefix + path, body, headers,
                                            params)

    def create_lbdc(self, name, type, ccu_count, billing, desc=None, renew=None, client_token=None, config=None):
        """

        The method of lbdc to be created.
        :param name:
            name
        :type name: str

        :param type:
            lbdc type
        :type type: str

        :param ccu_count:
            count of Cluster Capacity Unit
        :type ccu_count: int

        :param billing:
           order_configuration
        :type billing:Billing

        :param desc:
            description of the cluster
        :type desc: string

        :param renew:
           reservation info of order_configuration
        :type renew:Billing.reservation

        :param client_token:
            An ASCII string whose length is less than 64.
            The request will be idempotent if clientToken is provided.
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token
        }

        body = {
            'name': name,
            'type': type,
            'ccuCount': ccu_count,
            'billing': {
                'paymentTiming': billing.payment_timing,
                'reservation': {
                    'reservationLength': billing.reservation_length
                }
            }
        }
        if desc is not None:
            body['desc'] = desc
        if renew is not None:
            body['renewReservation'] = {
                'reservationLength': billing.reservation_length
            }
        return self._send_request(http_methods.POST, LbdcClient.path, body=json.dumps(body), params=params,
                                  config=config)

    def upgrade_lbdc(self, lbdc_id, ccu_count, action=b'resize', client_token=None, config=None):
        """
        The method of lbdc to be upgrade.

        :param lbdc_id: lbdc id
        :type lbdc_id: str

        :param ccu_count: count of Cluster Capacity Unit
        :type ccu_count: int

        :param action: action to upgrade lbdc
        :type action: str

        :param client_token:
            An ASCII string whose length is less than 64.
            The request will be idempotent if clientToken is provided.
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """

        path = LbdcClient.path + b'/' + compat.convert_to_bytes(lbdc_id)

        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token,
            action: '',
        }

        body = {
            'ccuCount': ccu_count,
        }

        return self._send_request(http_methods.PUT, path, body=json.dumps(body), params=params,
                                  config=config)

    def renew_lbdc(self, lbdc_id, billing, action=b'purchaseReserved', client_token=None, config=None):
        """

        renew lbdc

        :param lbdc_id:
            The id of lbdc.
        :type lbdc_id: str

        :param billing: order_configuration
        :type billing:Billing

        :param action: action to update lbdc
        :type action: str

        :param client_token:
            An ASCII string whose length is less than 64.
            The request will be idempotent if clientToken is provided.
            If the clientToken is not specified by the user, a random String generated by default algorithm will
            be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = LbdcClient.path + b'/' + compat.convert_to_bytes(lbdc_id)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token,
            action: '',
        }

        body = {
            'billing': {
                'reservation': {
                    'reservationLength': billing.reservation_length
                }
            }
        }
        return self._send_request(http_methods.PUT, path, body=json.dumps(body), params=params,
                                  config=config)

    def list_lbdc(self, lbdc_id=None, name=None, config=None):
        """

        return all lbdc list about query info

        :param lbdc_id: lbdc id
        :type lbdc_id: str

        :param name: lbdc name
        :type name: str

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        params = {}
        if lbdc_id is not None:
            params[b'id'] = lbdc_id
        if name is not None:
            params[b'name'] = name

        return self._send_request(http_methods.GET, LbdcClient.path, params=params, config=config)

    def get_lbdc(self, lbdc_id, config=None):
        """

        Get the detail information of lbdc.

        :param lbdc_id:
            The id of lbdc.
        :type lbdc_id: str

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = LbdcClient.path + b'/' + compat.convert_to_bytes(lbdc_id)

        return self._send_request(http_methods.GET, path, config=config)

    def update_lbdc(self, lbdc_id, name=None, desc=None, client_token=None, config=None):
        """

        renew lbdc

        :param lbdc_id:
            The id of lbdc.
        :type lbdc_id: string

        :param name:
            The name of lbdc
        :type name: str

        :param desc: description
        :type desc: str

        :param client_token:
            An ASCII string whose length is less than 64.
            The request will be idempotent if clientToken is provided.
            If the clientToken is not specified by the user, a random String generated by default algorithm will
            be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = LbdcClient.path + b'/' + compat.convert_to_bytes(lbdc_id)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token
        }

        body = {}
        if name is not None:
            body['name'] = name
        if desc is not None:
            body['desc'] = desc
        return self._send_request(http_methods.PUT, path, body=json.dumps(body), params=params,
                                  config=config)

    def list_lbdc_blb(self, lbdc_id, config=None):
        """

        return all lbdc list about query info

        :param lbdc_id: lbdc id
        :type lbdc_id:string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = LbdcClient.path + b'/' + compat.convert_to_bytes(lbdc_id) + b'/blb'

        return self._send_request(http_methods.GET, path, config=config)
