# -*- coding: utf-8 -*-
import pytest
import sys
import random
from .test_base_class import TestBaseClass
from aerospike import exception as e

aerospike = pytest.importorskip("aerospike")
try:
    import aerospike
except:
    print("Please install aerospike python client.")
    sys.exit(1)


class TestListRemove(object):

    @pytest.fixture(autouse=True)
    def setup(self, request, as_connection):
        keys = []
        for i in range(5):
            key = ('test', 'demo', i)
            rec = {'name': 'name%s' %
                   (str(i)),
                   'contact_no': [i, i + 1],
                   'city': ['Pune', 'Dehli']}
            self.as_connection.put(key, rec)
            keys.append(key)
        key = ('test', 'demo', 2)
        self.as_connection.list_append(key, "contact_no", [45, 50, 80])
        keys.append(key)

        def teardown():
            """
            Teardown method.
            """
            for key in keys:
                try:
                    as_connection.remove(key)
                except e.RecordNotFound:
                    pass

        request.addfinalizer(teardown)

    def test_pos_list_remove_with_correct_paramters(self):
        """
        Invoke list_remove() pop string with correct parameters
        """
        key = ('test', 'demo', 1)

        status = self.as_connection.list_remove(key, "contact_no", 0)
        assert status == 0

        (key, _, bins) = self.as_connection.get(key)
        assert bins == {
            'city': ['Pune', 'Dehli'], 'contact_no': [2], 'name': 'name1'}

    def test_pos_list_remove_with_correct_policy(self):
        """
        Invoke list_remove() remove list with correct policy
        """
        key = ('test', 'demo', 2)
        policy = {
            'timeout': 1000,
            'retry': aerospike.POLICY_RETRY_ONCE,
            'commit_level': aerospike.POLICY_COMMIT_LEVEL_MASTER
        }

        status = self.as_connection.list_remove(
            key, 'contact_no', 2, {}, policy)
        assert status == 0

        (key, _, bins) = self.as_connection.get(key)
        assert bins == {
            'city': ['Pune', 'Dehli'], 'contact_no': [2, 3], 'name': 'name2'}

    # Negative Tests
    def test_neg_list_remove_with_no_parameters(self):
        """
        Invoke list_remove() without any mandatory parameters.
        """
        with pytest.raises(TypeError) as typeError:
            self.as_connection.list_remove()
        assert "argument 'key' (pos 1)" in str(
            typeError.value)

    def test_neg_list_remove_with_incorrect_policy(self):
        """
        Invoke list_remove() with incorrect policy
        """
        key = ('test', 'demo', 1)
        policy = {
            'timeout': 0.5
        }
        try:
            self.as_connection.list_remove(key, "contact_no", 0, {}, policy)

        except e.ParamError as exception:
            assert exception.code == -2
            assert exception.msg == "timeout is invalid"

    def test_neg_list_remove_with_nonexistent_key(self):
        """
        Invoke list_remove() with non-existent key
        """
        if self.server_version < [3, 15, 2]:
            pytest.skip("Change of error beginning in 3.15")
        charSet = 'abcdefghijklmnopqrstuvwxyz1234567890'
        minLength = 5
        maxLength = 30
        length = random.randint(minLength, maxLength)
        key = ('test', 'demo', ''.join(map(lambda unused:
                                           random.choice(charSet),
                                           range(length))) + ".com")

        with pytest.raises(e.RecordNotFound):
            self.as_connection.list_remove(key, "contact_no", 0)

    def test_neg_list_remove_with_nonexistent_bin(self):
        """
        Invoke list_remove() with non-existent bin