# -*- coding: utf-8 -*-
import sys
import codecs
import hashlib
from datacloud.dev_utils.logging.logger import get_basic_logger
VERSION = sys.version_info[0]

logger = get_basic_logger(__name__)


def count_md5(text):
    """Calculates hex form of MD5 hash for given string

    >>> count_md5(normalize_email("sample@yandex.ru"))
    '7416adeec1ace820b2bad2f846a3578e'
    >>> count_md5(normalize_email("  sAmpLe@yandex.ru "))
    '7416adeec1ace820b2bad2f846a3578e'
    >>> count_md5(normalize_email("x-product@yandex-team.ru"))
    '7c8a1c75f84a335352c45bf1fbc1ab89'
    >>> count_md5(normalize_phone("71234567890"))
    '5a893224859c93b3be4c1be4389dc58f'
    >>> count_md5(normalize_phone("71234567891"))
    'b1bb37a4e1464a9f7535dad0dd456d34'
    >>> count_md5(normalize_phone("+7(123)456-78-90"))
    '5a893224859c93b3be4c1be4389dc58f'
    >>> count_md5(normalize_phone("8-1-2-3-4-5-67890 "))
    '5a893224859c93b3be4c1be4389dc58f'
    """
    return hashlib.md5(text.encode()).hexdigest()


def normalize_email(email):
    """Transforms email to normal form aaaa@aaa.aa

    >>> normalize_email("sample@yandex.ru")
    'sample@yandex.ru'
    >>> normalize_email("  sAmpLe@yandex.ru ")
    'sample@yandex.ru'
    >>> normalize_email("x-product@yandex-team.ru")
    'x-product@yandex-team.ru'
    """
    email = email.strip().lower()
    if len(email.split("@")) != 2:
        logger.debug("invalid email: %r", email)
        return None
    return email


def normalize_phone(phone):
    """Transforms phone to Crypta format 7xxxxxxxxxx

    >>> normalize_phone("71234567890")
    '71234567890'
    >>> normalize_phone("71234567891")
    '71234567891'
    >>> normalize_phone("+7(123)456-78-90")
    '71234567890'
    >>> normalize_phone("8-1-2-3-4-5-67890 ")
    '71234567890'
    >>> normalize_phone("1-2-3-4-5-67890 \\n\\t\\r")
    '71234567890'
    >>> normalize_phone(u"+7(123)456-78-90")
    u'71234567890'
    """
    phone_digits = ''.join(c for c in phone if c.isdigit())

    if len(phone_digits) == 0:
        logger.critical("  invalid phone: %s", phone)
        raise ValueError("invalid phone: {}".format(phone))
    elif len(phone_digits) == len("1234567890"):
        phone_digits = "7" + phone_digits
    if phone_digits[0] == "8" and len(phone_digits) == len("81234567890"):
        phone_digits = "7" + phone_digits[1:]
    return phone_digits


def normalize_crypta_phone(phone):
    phone = phone.strip()
    if phone[0] == "+":
        phone = phone[1:]
    return phone


def encode_as_uint64(string):
    """
    Encodes string as uint64.

    >>> encode_as_uint64("")
    7203772011789518145
    >>> encode_as_uint64("na gorshke sidel korol")
    7676862522229347065
    """
    return encode_hash_as_uint64(hashlib.md5(string.encode('utf-8')).digest())


def encode_hexhash_as_uint64(hexhash_string):
    """
    Encodes hex md5 hash string as uint64.

    >>> encode_hexhash_as_uint64(count_md5(""))
    7203772011789518145
    >>> encode_hexhash_as_uint64(count_md5("na gorshke sidel korol"))
    7676862522229347065
    """
    return encode_hash_as_uint64(codecs.decode(hexhash_string, 'hex'))


def encode_hash_as_uint64(hash_string):
    """
    Encodes md5 hash string as uint64. Ported from Arcadia.
    see https://a.yandex-team.ru/arc/trunk/arcadia/yabs/server/util/md5.cpp?rev=2609413#L3

    >>> encode_hash_as_uint64(hashlib.md5("").digest())
    7203772011789518145
    >>> encode_hash_as_uint64(hashlib.md5("na gorshke sidel korol").digest())
    7676862522229347065
    """
    if VERSION == 2:
        hash_bytes = [ord(c) for c in hash_string]
    if VERSION == 3:
        hash_bytes = [c for c in hash_string]
    res = 0
    for i in [3, 2, 1, 0]:
        res |= (hash_bytes[0 + i] ^ hash_bytes[8 + i]) << ((3 - i) << 3)
        res |= (hash_bytes[4 + i] ^ hash_bytes[12 + i]) << ((7 - i) << 3)
    return res
