# -*- coding: utf-8 -*-

# Copyright (c) 2021 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 EIP TP.
"""

import copy
import json
import logging
import uuid

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

_logger = logging.getLogger(__name__)


class EipTpClient(BceBaseClient):
    """
    EIP_TP sdk client
    """
    version = b'/v1'
    prefix = b'/eiptp'

    def __init__(self, config=None):
        """
        :type config: baidubce.BceClientConfiguration
        :param config:
        """
        BceBaseClient.__init__(self, config)

    @required(reservation_length=int,
              capacity=str)
    def create_eip_tp(self, reservation_length, capacity, deduct_policy=None, package_type=None,
                      client_token=None, config=None):
        """
        Create an eip_tp with the specified options.

        :type reservation_length: int
        :param reservation_length: the reservation length of the eip_tp including 1, 6 and 12 months.

        :type capacity: string
        :param capacity: the capacity of the eip_tp.
        When reservationLength = 1 => capacity: {"10G"/"50G"/"100G"/"500G"/"1T"/"5T"/"10T"/"50T"}
        When reservationLength = 6 => capacity: {"60G"/"300G"/"600G"/"3T"/"6T"/"30T"/"60T"/"300T"}
        When reservationLength = 12 => capacity: {"1T"/"10T"/"50T"/"100T"/"500T"/"1P"}

        :type deduct_policy: string
        :param deduct_policy: the deduct policy of the eip_tp including 'FullTimeDurationPackage'
        and 'TimeDurationPackage'.
        The default deduct policy is 'FullTimeDurationPackage', the optional parameter.

        :type package_type: string
        :param package_type: the eip_tp package type.
        The default package type is 'WebOutBytes', the optional parameter.

        :type client_token: string
        :param client_token: if the clientToken is not specified by the user,
         a random string generated by default algorithm will be used.

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: created eip_tp id, for example,{"id":"tp-xxxxxxxxxx"}
        """
        body = {
            'reservationLength': reservation_length,
            'capacity': capacity
        }
        if deduct_policy is not None:
            body['deductPolicy'] = deduct_policy
        if package_type is not None:
            body['packageType'] = package_type
        path = self._get_path()
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token
        }
        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(reservation_length=int, capacity=str)
    def get_eip_tp_price(self, reservation_length, capacity, deduct_policy=None,
                         package_type=None, client_token=None, config=None):
        """
        Get the price of creating an eip_tp with the specified options.

        :type reservation_length: int
        :param reservation_length: the reservation length of the eip_tp including 1, 6 and 12 months.

        :type capacity: string
        :param capacity: the capacity of the eip_tp.
        When reservationLength = 1 => capacity: {"10G"/"50G"/"100G"/"500G"/"1T"/"5T"/"10T"/"50T"}
        When reservationLength = 6 => capacity: {"60G"/"300G"/"600G"/"3T"/"6T"/"30T"/"60T"/"300T"}
        When reservationLength = 12 => capacity: {"1T"/"10T"/"50T"/"100T"/"500T"/"1P"}

        :type deduct_policy: string
        :param deduct_policy: the deduct policy of the eip_tp including 'FullTimeDurationPackage'
        and 'TimeDurationPackage'.
        The default deduct policy is 'FullTimeDurationPackage', the optional parameter.

        :type package_type: string
        :param package_type: the eip_tp package type.
        The default package type is 'WebOutBytes', the optional parameter.

        :type client_token: string
        :param client_token: if the clientToken is not specified by the user,
         a random string generated by default algorithm will be used.

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: eip_tp price, for example, {"price": "7.20000"}
        """
        body = {
            'reservationLength': reservation_length,
            'capacity': capacity
        }
        if deduct_policy is not None:
            body['deductPolicy'] = deduct_policy
        if package_type is not None:
            body['packageType'] = package_type

        path = utils.append_uri(self._get_path(), 'price')

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

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

    @required(id=str)
    def get_eip_tp_detail(self, id, config=None):
        """
        get the eip_tp's detail owned by the authenticated user by the passed eip_tp_id.

        :type id: string
        :param id: eip_tp's id.

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: detail of eip_tp, for example:
                {
                  "id":"tp-87V5cnkwqO",
                  "deductPolicy":"TimeDurationPackage",
                  "packageType":"WebOutBytes",
                  "status":"RUNNING",
                  "capacity": 10737418240,
                  "usedCapacity": 0,
                  "createTime":"2021-04-10T11:40:57Z",
                  "activeTime": "2021-04-10T11:41:16Z",
                  "expireTime:" "2021-05-10T11:41:16Z"
                }
        """

        path = utils.append_uri(self._get_path(), id)
        return self._send_request(http_methods.GET, path, params=None,
                                  config=config)

    def list_eip_tps(self, id=None, deduct_policy=None, status=None,
                     marker=None, max_keys=1000, config=None):
        """
        get a list of eip_tp owned by the authenticated filtered by specific conditions.

        :type id: string
        :param id: eip_tp's id, the optional parameter.

        :type deduct_policy: string
        :param deduct_policy: eip_tp's deduct policy, 'FullTimeDurationPackage' or 'TimeDurationPackage', the optional parameter.

        :type status: string
        :param status: eip_tp's status, 'RUNNING', 'EXPIRED' or 'USED_UP', the optional parameter.

        :type marker: string
        :param marker: The optional parameter marker specified in the original
         request to specify where in the results to begin listing.

        :type max_keys: int
        :param max_keys: The optional parameter to specifies the max number
         of list result to return. The default value is 1000.

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: list of eip_tp model, for example:
                {
                    "marker": "tp-87V5cnkwqO",
                    "maxKeys": 1,
                    "nextMarker": "tp-Qn65tYXAx3",
                    "isTruncated": true,
                    "packageList": [
                        {
                           "id":"tp-87V5cnkwqO",
                           "deductPolicy":"TimeDurationPackage",
                           "packageType":"WebOutBytes",
                           "status":"RUNNING",
                           "capacity": 10737418240,
                           "usedCapacity": 0,
                           "createTime":"2021-04-10T11:40:57Z",
                           "activeTime": "2021-04-10T11:41:16Z",
                           "expireTime:" "2021-05-10T11:41:16Z"
                        }
                    ]
                }
       """

        path = self._get_path()
        params = {}
        if id is not None:
            params[b'id'] = id
        if deduct_policy is not None:
            params[b'deductPolicy'] = deduct_policy
        if status is not None:
            params[b'status'] = status
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys
        return self._send_request(http_methods.GET, path, params=params,
                                  config=config)

    @staticmethod
    def _generate_default_client_token():
        """
        default client token by uuid1
        """
        return uuid.uuid1()

    @staticmethod
    def _get_path(prefix=None):
        """
        :type prefix: string
        :param prefix: path prefix
        """
        if prefix is None:
            prefix = EipTpClient.prefix
        return utils.append_uri(EipTpClient.version, prefix)

    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, path, body, headers,
                                            params)
