"""Tests for list exercises"""
import unittest

from helpers import BaseTestCase
from lists import (
    combine_lists,
    glink,
    rotate_list,
    characters,
    reverse_words,
    ith_item_power,
    natural_sort,
)


class CombineListsTests(BaseTestCase):

    """Tests for combine_lists."""

    def test_two_lists(self):
        self.assertEqual(combine_lists([1, 2, 3], [4, 5, 6]), [1, 2, 3, 4, 5, 6])

    def test_lists_unchanged(self):
        first = [1, 2, 3]
        second = [4, 5, 6]
        combine_lists(first, second)
        self.assertEqual(first, [1, 2, 3])
        self.assertEqual(second, [4, 5, 6])

    def test_one_empty_list(self):
        self.assertEqual(combine_lists([1, 2], []), [1, 2])


class GlinkTests(BaseTestCase):

    """Tests for glink."""

    def test_valid_url(self):
        url = (
            "https://drive.google.com/file/d/" +
            "1q65D27qS2Oxb5zoMpTvknCoRlWIAi4MD/view?usp=sharing"
        )
        expected = (
            "https://drive.google.com/uc?export=view" +
            "&id=1q65D27qS2Oxb5zoMpTvknCoRlWIAi4MD"
        )
        self.assertEqual(glink(url), expected)

    def test_different_valid_url(self):
        url = (
            "https://drive.google.com/file/d/" +
            "1uWRiTEirYlKEgOr5tSWE4XPCIuTctsXg/view?usp=sharing"
        )
        expected = (
            "https://drive.google.com/uc?export=view" +
            "&id=1uWRiTEirYlKEgOr5tSWE4XPCIuTctsXg"
        )
        self.assertEqual(glink(url), expected)

    def test_file_id_with_special_characters(self):
        url = (
            "https://drive.google.com/file/d/" +
            "1Zs13WJYdZL1pNZP0dCIXkWau_tZOjK3mmJz0KNq4I30/view?usp=sharing"
        )
        expected = (
            "https://drive.google.com/uc?export=view" +
            "&id=1Zs13WJYdZL1pNZP0dCIXkWau_tZOjK3mmJz0KNq4I30"
        )
        self.assertEqual(glink(url), expected)


class RotateListTests(BaseTestCase):

    """Tests for rotate_list."""

    def test_four_items(self):
        numbers = [1, 2, 3, 4]
        self.assertEqual(rotate_list(numbers), 1)
        self.assertEqual(numbers, [2, 3, 4, 1])

    def test_two_items(self):
        numbers = ["a", "b"]
        self.assertEqual(rotate_list(numbers), "a")
        self.assertEqual(numbers, ["b", "a"])

    def test_one_item(self):
        numbers = [0]
        self.assertEqual(rotate_list(numbers), 0)
        self.assertEqual(numbers, [0])

    @unittest.skip("Comment out this line for Reverse Rotate")
    def test_reverse_rotate(self):
        numbers = [1, 2, 3, 4]
        self.assertEqual(rotate_list(numbers, reverse=True), 4)
        self.assertEqual(numbers, [4, 1, 2, 3])

    @unittest.skip("Comment out this line for Reverse Rotate")
    def test_not_reverse(self):
        numbers = [4, 1, 2, 3]
        self.assertEqual(rotate_list(numbers, reverse=False), 4)
        self.assertEqual(numbers, [1, 2, 3, 4])


class CharactersTests(BaseTestCase):

    """Tests for characters."""

    def test_without_sorting(self):
        self.assertEqual(
            characters("hello"),
            ["h", "e", "l", "l", "o"],
        )
        self.assertEqual(
            characters("hello", sort=False),
            ["h", "e", "l", "l", "o"],
        )

    def test_with_sorting(self):
        self.assertEqual(
            characters("hello", sort=True),
            ["e", "h", "l", "l", "o"],
        )

    def test_lowercases_letters(self):
        self.assertEqual(
            characters("Trey Hunner"),
            ["t", "r", "e", "y", " ", "h", "u", "n", "n", "e", "r"],
        )

    def test_lowercasing_and_sorting(self):
        self.assertEqual(
            characters("Trey Hunner", sort=True),
            [" ", "e", "e", "h", "n", "n", "r", "r", "t", "u", "y"],
        )


class ReverseWordOrder(BaseTestCase):

    """Tests for reverse_words."""

    def test_three_words(self):
        self.assertEqual(reverse_words("who is this"), "this is who")

    def test_four_words(self):
        self.assertEqual(reverse_words("words some are these"), "these are some words")

    def test_one_word(self):
        self.assertEqual(reverse_words("hello"), "hello")

    def test_empty_string(self):
        self.assertEqual(reverse_words(""), "")


class IthItemsPowerTests(BaseTestCase):

    """Tests for ith_item_power."""

    def test_square(self):
        self.assertEqual(ith_item_power([3, 2, 5], 2), 25)

    def test_fourth_power(self):
        self.assertEqual(ith_item_power([5, 6, 2, 7, 3], 4), 81)

    def test_zeroth_power(self):
        self.assertEqual(ith_item_power([3, 2, 5], 0), 1)

    def test_negative_powers(self):
        self.assertEqual(ith_item_power([3, 2, 5], -1), 0.2)


class NaturalSortTests(BaseTestCase):

    """Tests for natural_sort."""

    def test_empty_iterable(self):
        self.assertEqual(natural_sort([]), [])
        self.assertEqual(natural_sort(()), [])
        self.assertEqual(natural_sort(set()), [])

    def test_all_lowercase_strings(self):
        self.assertEqual(
            natural_sort(["cake", "apple", "ball", "clover", "zoo"]),
            ["apple", "ball", "cake", "clover", "zoo"],
        )

    def test_some_uppercase(self):
        self.assertEqual(
            natural_sort(["Cake", "apple", "ball", "clover", "Zoo"]),
            ["apple", "ball", "Cake", "clover", "Zoo"],
        )

    def test_with_spaces(self):
        self.assertEqual(
            natural_sort(["Sarah Clarke", "Sara Hillard", "Sarah Chiu"]),
            ["Sara Hillard", "Sarah Chiu", "Sarah Clarke"],
        )


if __name__ == "__main__":
    from helpers import error_message

    error_message()
