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

# 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 EIP.
"""

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.services.eip.model import EipStatus

_logger = logging.getLogger(__name__)


class EipClient(BceBaseClient):
    """
    eip sdk client
    """
    version = b'/v1'
    prefix = b'/eip'
    transfer_prefix = "/transfer"

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

    def create_eip(self, bandwidth_in_mbps, name=None, billing=None,
               route_type=None, ip_version=None, tags=None,
               resource_group_id=None, auto_renew_time_unit=None,
               auto_renew_time=None, delete_protect=None,
               client_token=None, config=None):
        """
        Create an eip with the specified options.

        :type bandwidth_in_mbps: int
        :param bandwidth_in_mbps: specify the bandwidth in Mbps

        :type name: string
        :param name: name of eip. The optional parameter

        :type billing: Billing
        :param billing: billing information. The optional parameter

        :type route_type: string
        :param route_type: route type (BGP or BGP_S)

        :type ip_version: string
        :param ip_version: IP version (ipv4 or ipv6), default ipv4

        :type tags: list
        :param tags: list of tag key-value pairs

        :type resource_group_id: string
        :param resource_group_id: resource group ID

        :type auto_renew_time_unit: string
        :param auto_renew_time_unit: auto renew time unit (month or year)

        :type auto_renew_time: int
        :param auto_renew_time: auto renew time length

        :type delete_protect: bool
        :param delete_protect: enable delete protection

        :type client_token: string
        :param client_token: idempotent token

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: created eip address, for example,{"eip":"x.x.x.x"}
        """
        body = {
            'bandwidthInMbps': bandwidth_in_mbps
        }
        if name is not None:
            body['name'] = name
        if route_type is not None:
            body['routeType'] = route_type
        if ip_version is not None:
            body['ipVersion'] = ip_version
        if tags is not None:
            body['tags'] = tags
        if resource_group_id is not None:
            body['resourceGroupId'] = resource_group_id
        if auto_renew_time_unit is not None:
            body['autoRenewTimeUnit'] = auto_renew_time_unit
        if auto_renew_time is not None:
            body['autoRenewTime'] = auto_renew_time
        if delete_protect is not None:
            body['deleteProtect'] = delete_protect

        if billing is None:
            body['billing'] = {
                'paymentTiming': 'Postpaid',
                'billingMethod': 'ByBandwidth'
            }
        else:
            body['billing'] = {
                'paymentTiming': billing.payment_timing,
                'billingMethod': billing.billing_method,
                'reservation': {
                    'reservationLength': billing.reservation_length,
                    'reservationTimeUnit': billing.reservation_time_unit
                }
            }
        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)

    def resize_eip(self, eip, new_bandwidth_in_mbps, client_token=None,
                   config=None):
        """
        Resizing eip

        :type eip: string
        :param eip: eip address to be resized

        :type new_bandwidth_in_mbps: int
        :param new_bandwidth_in_mbps: specify new bandwidth in Mbps for eip

        :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: BceResponse
        """
        body = {
            'newBandwidthInMbps': new_bandwidth_in_mbps
        }
        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'resize': b'',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params,
                                  body=json.dumps(body), config=config)

    def purchase_reserved_eip(self, eip, billing=None, client_token=None,
                              config=None):
        """
        PurchaseReserved eip with fixed duration,only Prepaid eip can do this

        :type eip: string
        :param eip: eip address to be renewed

        :type billing: Billing
        :param billing: billing information. The optional parameter,
         default reservationLength is 1

        :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: BceResponse
        """
        if billing is None:
            body = {
                'billing': {
                    'reservation': {
                        'reservationLength': 1,
                        'reservationTimeUnit': 'Month'
                    }
                }
            }
        else:
            body = {
                'billing': {
                    'reservation': {
                        'reservationLength': billing.reservation_length,
                        'reservationTimeUnit': billing.reservation_time_unit
                    }
                }
            }
        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'purchaseReserved': b'',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params,
                                  body=json.dumps(body), config=config)
    
    def start_auto_renew_eip(self, eip, auto_renew_time_unit=None, auto_renew_time=None, 
                             client_token=None, config=None):
        """
        Enable auto renew for specified EIP.

        :type eip: string
        :param eip: eip address to be enable to auto-renew.

        :type auto_renew_time_unit: string
        :param auto_renew_time_unit: time unit of auto_renew_time, default 'Month'.

        :type auto_renew_time: int
        :param auto_renew_time: the unit of time for auto renew,
        default auto_renew_time is 1

        :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: BceResponse
        """
        if auto_renew_time_unit is None:
            auto_renew_time_unit = 'month'
        if auto_renew_time is None:
            auto_renew_time = 1
        body = {
            'autoRenewTimeUnit': auto_renew_time_unit,
            'autoRenewTime': auto_renew_time
        }
        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'startAutoRenew': b'',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params,
                                  body=json.dumps(body), config=config)
    
    def stop_auto_renew_eip(self, eip, client_token=None, config=None):
        """
        Disable auto renew for specified EIP.

        :type eip: string
        :param eip: eip address to be disable to auto-renew.

        :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: BceResponse
        """

        path = utils.append_uri(self._get_path(), eip)

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

        # Sending the HTTP request
        return self._send_request(http_methods.PUT, path, params=params, config=config)


    def bind_eip(self, eip, instance_type, instance_id, instance_ip=None, client_token=None,
                 config=None):
        """
        bind the eip to a specified instanceId and instanceType

        :type eip: string
        :param eip: eip address to be bound

        :type instance_type: string
        :param instance_type: type of instance to be bound(BCC BLB et.)

        :type instance_id: string
        :param instance_id: id of instance to be bound

        :type instance_ip: string
        :param instance_ip: specific IP address within the instance to bind

        :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: BceResponse
        """
        body = {
            'instanceType': instance_type,
            'instanceId': instance_id
        }
        if instance_ip is not None:
            body['instanceIp'] = instance_ip
        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'bind': b'',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params,
                                  body=json.dumps(body), config=config)

    def unbind_eip(self, eip, client_token=None, config=None):
        """
        unbind the eip from a specified instance

        :type eip: string
        :param eip: eip address to be unbound

        :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: BceResponse
        """
        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'unbind': b'',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params,
                                  config=config)

    def release_eip(self, eip, client_token=None, config=None):
        """
        release the eip(delete operation)
        Only the Postpaid instance or Prepaid which is expired can be released.
        if the eip has been bound, must unbind before releasing.

        :type eip: string
        :param eip: eip address to be released

        :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: BceResponse
        """
        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token
        }
        return self._send_request(http_methods.DELETE, path, params=params,
                                  config=config)
    
    def direct_eip(self, eip, client_token=None, config=None):
        """
        turn on EIP pass through with the specific parameters.

        :type eip: string
        :param eip: the specific EIP.

        :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: None

        :return: BceResponse
        """
        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'direct': b'',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params, config=config)
    
    def undirect_eip(self, eip, client_token=None, config=None):
        """
        Remove the direction of an EIP from a specific instance.
        
        :type eip: string
        :param eip: the EIP address to undirect.

        :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: None

        :return: BceResponse
        """
        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'unDirect': b'',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params, config=config)


    def list_eips(self, eip=None, instance_type=None, ip_version=None, instance_id=None,
                  status=None, marker=None, max_keys=1000,
                  name=None, eip_ids=None, config=None):
        """
        get a list of eip owned by the authenticated user and specified
        conditions. we can Also get a single eip function  through this
        interface by eip condition

        :type eip: string
        :param eip: eip address condition

        :type instance_type: string
        :param instance_type: bound instance type condition

        :type instance_id: string
        :param instance_id: bound instance id condition
        if query by the instanceId or instanceType condition, must provides
         both of them at the same time

        :type status: string
        :param status of eip condition
        if query by the status condition, must provides

        :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 name: string
        :param name: eip name condition

        :type eip_ids: string
        :param eip_ids: comma-separated EIP IDs for batch query

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: list of eip model, for example:
                {
                    "eipList": [
                        {
                            "name":"eip-xxxxxxx-1",
                            "eip": "x.x.x.x",
                            "status":"binded",
                            "instanceType": "BCC",
                            "instanceId": "i-xxxxxxx",
                            "bandwidthInMbps": 5,
                            "paymentTiming":"Prepaid",
                            "billingMethod":"ByBandwidth",
                            "createTime":"2016-03-08T08:13:09Z",
                            "expireTime":"2016-04-08T08:13:09Z"
                        },
                        {
                            "name":"eip-xxxxxxx-1",
                            "eip": "x.x.x.x",
                            "status":"binded",
                            "instanceType": "BCC",
                            "instanceId": "i-xxxxxxx",
                            "bandwidthInMbps": 1,
                            "paymentTiming":"Postpaid",
                            "billingMethod":"ByTraffic",
                            "createTime":"2016-03-08T08:13:09Z",
                            "expireTime":null
                        },
                    ],
                    "marker":"eip-xxxxxxx-1",
                    "isTruncated": true,
                    "nextMarker": "eip-DCB50387",
                    "maxKeys": 2
                }
        """
        path = self._get_path()
        params = {}
        if eip is not None:
            params[b'eip'] = eip
        if instance_type is not None:
            params[b'instanceType'] = instance_type
        if instance_id is not None:
            params[b'instanceId'] = instance_id
        if name is not None:
            params[b'name'] = name
        if status is not None and isinstance(status, EipStatus):
            params[b'status'] = status.value
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys
        if ip_version is not None:
            params[b'ipVersion'] = ip_version
        if eip_ids is not None:
            params[b'eipIds'] = eip_ids
        return self._send_request(http_methods.GET, path, params=params,
                                  config=config)

    def list_eip_recycle(self, eip=None, name=None, marker=None, max_keys=1000, config=None):
        """
        list all EIP in the recycle bin with the specific parameters.

        :type eip: string
        :param eip: eip address condition

        :type name: string
        :param name: eip name condition

        :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: None

        :return: list of eip model, for example:
                {
                    "eipList": [
                        {
                            "name":"eip-xxxxxxx-1",
                            "eip": "x.x.x.x",
                            "eip_id":"ip-xxxxxxxx",
                            "status": "paused",
                            "route_type": "BGP",
                            "bandwidth_in_mbps": 5,
                            "payment_timing":"Prepaid",
                            "billing_method":"ByBandwidth",
                            "recycle_time":"2016-03-08T08:13:09Z",
                            "scheduled_delete_time":"2016-04-08T08:13:09Z"
                        },
                        {
                            "name":"eip-xxxxxxx-2",
                            "eip": "x.x.x.x",
                            "eip_id":"ip-xxxxxxxx",
                            "status": "paused",
                            "route_type": "BGP",
                            "bandwidth_in_mbps": 10,
                            "payment_timing":"Postpaid",
                            "billing_method":"ByBandwidth",
                            "recycle_time":"2016-03-08T08:13:09Z",
                            "scheduled_delete_time":"2016-04-08T08:13:09Z"
                        },
                    ],
                    "marker":"ip-xxxxxxxx",
                    "is_truncated": true,
                    "max_keys": 1000
                }
        """
        path = utils.append_uri(self._get_path(), 'recycle')
        params = {}
        if eip is not None:
            params[b'eip'] = eip
        if name is not None:
            params[b'name'] = name
        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)
    
    def optional_delete_eip(self, eip, release_to_recycle=False, client_token=None, config=None):
        """
        delete an EIP with additional options.

        :type eip: string
        :param eip: the EIP address to delete.

        :type release_to_recycle: bool
        :param release_to_recycle: flag to release EIP to recycle bin.

        :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: BceResponse
        """

        path = utils.append_uri(self._get_path(), eip)

        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token,
            b'releaseToRecycle': release_to_recycle
        }
        return self._send_request(http_methods.DELETE, path, params=params, config=config)

    def restore_recycle_eip(self, eip, client_token=None, config=None):
        """
        restore an EIP from the recycle bin.

        :type eip: string
        :param eip: eip address to be restored from recycle bin.

        :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: BceResponse
        """

        path = utils.append_uri(self._get_path(), 'recycle', eip)

        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'restore': b'',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params, config=config)

    def delete_recycle_eip(self, eip, client_token=None, config=None):
        """
        delete an EIP from the recycle bin.

        :type eip: string
        :param eip: eip address to be delete from recycle bin.

        :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: BceResponse
        """

        path = utils.append_uri(self._get_path(), 'recycle', eip)

        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token
        }
        return self._send_request(http_methods.DELETE, path, params=params, config=config)

    def change_eip_to_prepay(self, eip, purchase_length, bandwidth, client_token=None, config=None):
        """
        Change EIP billing method from postpaid to prepaid.

        :type eip: string
        :param eip: eip address to change billing method

        :type purchase_length: int
        :param purchase_length: purchase duration in months (1-9, 12, 24, 36)

        :type bandwidth: int
        :param bandwidth: bandwidth for prepaid EIP

        :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: BceResponse
        """
        body = {
            'purchaseLength': purchase_length,
            'bandWidth': bandwidth
        }

        path = utils.append_uri(self._get_path(), eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'action': b'TO_PREPAY',
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params,
                                  body=json.dumps(body), config=config)

    def refund_prepay_eip(self, eip, client_token=None, config=None):
        """
        Refund a prepaid EIP.

        :type eip: string
        :param eip: eip address to refund

        :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: BceResponse
        """
        path = utils.append_uri(self._get_path(), 'refund', eip)
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params, config=config)

    def update_eip_delete_protect(self, eip, delete_protect, client_token=None, config=None):
        """
        Update EIP delete protection setting.

        :type eip: string
        :param eip: eip address to update

        :type delete_protect: bool
        :param delete_protect: enable or disable delete protection

        :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: BceResponse
        """
        body = {
            'deleteProtect': delete_protect
        }

        path = utils.append_uri(self._get_path(), eip, 'deleteProtect')
        if client_token is None:
            client_token = self._generate_default_client_token()
        params = {
            b'clientToken': client_token
        }
        return self._send_request(http_methods.PUT, path, params=params,
                                  body=json.dumps(body), config=config)

    def create_eip_transfer(self, transfer_type, transfer_resource_list, to_user_id,
                            client_token=None, config=None):
        """
        Create an EIP resource transfer task to transfer resources from one account to another.

        :type transfer_type: string
        :param transfer_type: Transfer resource type, should be 'eip'

        :type transfer_resource_list: list
        :param transfer_resource_list: List of resource short IDs to transfer, max 30 items

        :type to_user_id: string
        :param to_user_id: Target account ID

        :type client_token: string
        :param client_token: Idempotent token. If not specified, a random string will be generated.

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: BceResponse
        """
        body = {
            'transferType': transfer_type,
            'transferResourceList': transfer_resource_list,
            'toUserId': to_user_id
        }

        path = utils.append_uri(self._get_path(EipClient.transfer_prefix))

        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)

    def cancel_eip_transfer(self, transfer_id_list, client_token=None, config=None):
        """
        Cancel EIP resource transfer tasks.

        :type transfer_id_list: list
        :param transfer_id_list: List of transfer task IDs to cancel, max 30 items

        :type client_token: string
        :param client_token: Idempotent token. If not specified, a random string will be generated.

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: BceResponse
        """
        body = {
            'transferIdList': transfer_id_list
        }

        path = utils.append_uri(self._get_path(EipClient.transfer_prefix))

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

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

    def reject_eip_transfer(self, transfer_id_list, client_token=None, config=None):
        """
        Reject EIP resource transfer tasks.

        :type transfer_id_list: list
        :param transfer_id_list: List of transfer task IDs to reject, max 30 items

        :type client_token: string
        :param client_token: Idempotent token. If not specified, a random string will be generated.

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: BceResponse
        """
        body = {
            'transferIdList': transfer_id_list
        }

        path = utils.append_uri(self._get_path(EipClient.transfer_prefix))

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

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

    def accept_eip_transfer(self, transfer_id_list, client_token=None, config=None):
        """
        Accept EIP resource transfer tasks.

        :type transfer_id_list: list
        :param transfer_id_list: List of transfer task IDs to accept, max 30 items

        :type client_token: string
        :param client_token: Idempotent token. If not specified, a random string will be generated.

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: BceResponse
        """
        body = {
            'transferIdList': transfer_id_list
        }

        path = utils.append_uri(self._get_path(EipClient.transfer_prefix))

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

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

    def list_eip_transfer(self, max_keys=None, marker=None, direction=None,
                           transfer_id=None, status=None,
                           fuzzy_transfer_id=None, fuzzy_instance_id=None,
                           fuzzy_instance_name=None, fuzzy_instance_ip=None,
                           config=None):
        """
        List EIP resource transfer tasks.

        :type max_keys: int
        :param max_keys: Maximum number of items per page, default 10

        :type marker: string
        :param marker: Pagination marker

        :type direction: string
        :param direction: 'sent' for initiated by me, 'received' for received by me

        :type transfer_type: string
        :param transfer_type: Transfer resource type

        :type transfer_id: string
        :param transfer_id: Transfer ID for exact query, multiple IDs separated by '_'

        :type status: string
        :param status: Status filter, default 'all'

        :type fuzzy_transfer_id: string
        :param fuzzy_transfer_id: Transfer ID fuzzy query

        :type fuzzy_instance_id: string
        :param fuzzy_instance_id: Instance ID fuzzy query

        :type fuzzy_instance_name: string
        :param fuzzy_instance_name: Instance name fuzzy query

        :type fuzzy_instance_ip: string
        :param fuzzy_instance_ip: Instance IP fuzzy query

        :type config: baidubce.BceClientConfiguration
        :param config:

        :return: list of transfer tasks, for example:
                {
                    "transferList": [...],
                    "marker": "tf-1l4m5etb",
                    "isTruncated": false,
                    "nextMarker": "...",
                    "maxKeys": 10
                }
        """
        path = utils.append_uri(self._get_path(EipClient.transfer_prefix))
        params = {}

        if max_keys is not None:
            params[b'maxKeys'] = max_keys
        if marker is not None:
            params[b'marker'] = marker
        if direction is not None:
            params[b'direction'] = direction
        if transfer_id is not None:
            params[b'transferId'] = transfer_id
        if status is not None:
            params[b'status'] = status
        if fuzzy_transfer_id is not None:
            params[b'fuzzyTransferId'] = fuzzy_transfer_id
        if fuzzy_instance_id is not None:
            params[b'fuzzyInstanceId'] = fuzzy_instance_id
        if fuzzy_instance_name is not None:
            params[b'fuzzyInstanceName'] = fuzzy_instance_name
        if fuzzy_instance_ip is not None:
            params[b'fuzzyInstanceIp'] = fuzzy_instance_ip

        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 = EipClient.prefix
        return utils.append_uri(EipClient.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)
