from typing import Iterable
import six
from typing import OrderedDict


def compare_anything(value1, value2):
    """Compare two whatever.

    They must be identical. Same type, same variable types, etc.
    ``1 != 1.0``, to ble clear. See examples.

    Examples
    --------
    >>> compare_anything(1, 2)
    False
    >>> compare_anything(int(1), float(1))
    False
    >>> compare_anything([1], 2)
    False
    >>> compare_anything([1], [2])
    False
    >>> compare_anything([1, 2], [1, 2])
    True
    >>> compare_anything({1: 2}, [1, 2])
    False
    >>> compare_anything({1: 2}, {1: 2})
    True
    >>> compare_anything({1: [2]}, {1: [2]})
    True
    >>> compare_anything({1: {1: 2}}, {1: {1: 2}})
    True
    >>> compare_anything({1: {1: 2}, 2: {1: 2}}, {2: {1: 2}, 1: {1: 2}})
    True
    >>> compare_anything({1: {1: "2"}, 2: {1: 2}}, {2: {1: 2}, 1: {1: "2"}})
    True
    >>> compare_anything("aa", "aa")
    True
    >>> compare_anything(u"aa", b"aa")
    False
    >>> compare_anything("aa", "bb")
    False
    >>> compare_anything({1: {1: "2"}, 2: {1: 2}}, {})
    False
    """
    if not isinstance(value1, value2.__class__):
        return False

    if not isinstance(value1, Iterable) or \
            isinstance(value1, six.string_types):
        return value1 == value2
    elif not isinstance(value1, dict):
        for i, j in zip(value1, value2):
            if not compare_anything(i, j):
                return False
    else:
        items1 = value1.items()
        items2 = value2.items()
        if len(list(items1)) != len(list(items2)):
            return False
        value1_sort = \
            OrderedDict(sorted(items1))
        value2_sort = \
            OrderedDict(sorted(items2))
        for i, j in zip(value1_sort.items(), value2_sort.items()):
            if not compare_anything(i, j):
                return False

    return True