import io, base64, hashlib
from urllib import parse


def base64_encode(input, output=None):
    """
    :param output:
    :param input: File pointer or str or bytes.
    :return:
    """
    if isinstance(input, bytes):
        return base64.b64encode(input)
    elif isinstance(input, str):
        return base64.b64encode(bytes(input, encoding='utf-8')).decode()
    else:
        return base64.encode(input, output)


def base64_decode(input, output=None):
    """
    :param output:
    :param input: File pointer or str or bytes.
    :return:
    """
    if isinstance(input, bytes):
        return base64.b64decode(input)
    elif isinstance(input, str):
        return base64.b64decode(bytes(input, encoding='utf-8')).decode()
    else:
        return base64.decode(input, output)


def hash_sum(method, input):
    """
    :param method:
    :param input: File pointer or str or bytes.
    :return:
    """
    hashChoose = eval('hashlib.' + method)
    if isinstance(input, bytes):
        return hashChoose(input).hexdigest()
    elif isinstance(input, str):
        return hashChoose(bytes(input, encoding='utf-8')).hexdigest()
    else:
        hashObject = hashChoose()
        bufferSize = io.DEFAULT_BUFFER_SIZE
        while True:
            data = input.read(bufferSize)
            if data:
                hashObject.update(data)
            else:
                break
        return hashObject.hexdigest()


def md5(input):
    from sys import _getframe as getframe
    return hash_sum(method=getframe().f_code.co_name, input=input)


def sha1(input):
    from sys import _getframe as getframe
    return hash_sum(method=getframe().f_code.co_name, input=input)


def sha224(input):
    from sys import _getframe as getframe
    return hash_sum(method=getframe().f_code.co_name, input=input)


def sha256(input):
    from sys import _getframe as getframe
    return hash_sum(method=getframe().f_code.co_name, input=input)


def sha384(input):
    from sys import _getframe as getframe
    return hash_sum(method=getframe().f_code.co_name, input=input)


def sha512(input):
    from sys import _getframe as getframe
    return hash_sum(method=getframe().f_code.co_name, input=input)


def urlencode(string):
    return parse.quote(str(string))


def urldecode(string):
    return parse.unquote(string)


if __name__ == '__main__':
    # Example.
    # print(base64_encode(open('./example', 'rb'), open('./example.base64', 'wb')))
    # print(base64_decode(open('./example.base64', 'rb'), open('./example.base64.decode', 'wb')))
    print(base64_encode('root'))
    print(base64_encode(bytes('root', encoding='utf-8')))
    print(base64_decode('cm9vdA=='))
    print(base64_decode(bytes('cm9vdA==', encoding='utf-8')))
    print(sha1('root'))
    print(sha224('root'))
    print(sha256('root'))
    print(sha384('root'))
    print(sha512('root'))
    # print(md5('root'))
    # print(md5(bytes('root', encoding='utf-8')))
    # print(md5(open('./example', 'rb')))
    print(urlencode('百度一下'))
    print(urldecode('%E7%99%BE%E5%BA%A6%E4%B8%80%E4%B8%8B'))
