"""
  @author: LinTao
  @time: 2022/10/3 15:49
  @desc:
"""

import random
import string
import time
from datetime import datetime
from io import BytesIO
from PIL import Image, ImageFont, ImageDraw
from smtplib import SMTP_SSL
from email.mime.text import MIMEText
from email.header import Header


class ImageCode:
    def rand_color(self):
        """生成用于绘制字符串的随机颜色(可以随意指定0-255之间的数字)"""
        red = random.randint(32, 200)
        green = random.randint(22, 255)
        blue = random.randint(0, 200)
        return red, green, blue

    def gen_text(self):
        """生成4位随机字符串"""
        # sample 用于从一个大的列表或字符串中，随机取得N个字符，来构建出一个子列表
        list = random.sample(string.ascii_letters, 5)
        return ''.join(list)

    def draw_lines(self, draw, num, width, height):
        """
        绘制干扰线
        :param draw: 图片对象
        :param num: 干扰线数量
        :param width: 图片的宽
        :param height: 图片的高
        :return:
        """
        for num in range(num):
            x1 = random.randint(0, width / 2)
            y1 = random.randint(0, height / 2)
            x2 = random.randint(0, width)
            y2 = random.randint(height / 2, height)
            draw.line(((x1, y1), (x2, y2)), fill='black', width=2)

    def draw_verify_code(self):
        """绘制验证码图片"""
        code = self.gen_text()
        width, height = 120, 50  # 设定图片大小，可根据实际需求调整
        im = Image.new('RGB', (width, height), 'white')  # 创建图片对象，并设定背景色为白色
        font = ImageFont.truetype(font='arial.ttf', size=40)  # 选择使用何种字体及字体大小
        draw = ImageDraw.Draw(im)  # 新建ImageDraw对象

        # 绘制字符串
        for i in range(4):
            draw.text((5 + random.randint(-3, 3) + 23 * i, 5 + random.randint(-3, 3)),
                      text=code[i], fill=self.rand_color(), font=font)
        self.draw_lines(draw, 4, width, height)  # 绘制干扰线
        # im.show()  # 如需临时调试，可以直接将生成的图片显示出来
        return im, code

    def get_code(self):
        """生成图片验证码并返回给控制器"""
        image, code = self.draw_verify_code()
        buf = BytesIO()
        image.save(buf, 'jpeg')
        bstring = buf.getvalue()
        return code, bstring


def send_email(self, receiver, ecode):
    """发送邮件"""
    sender = 'XXX <xxxxxxxxx@qq.com>'  # 邮箱账号和发件者签名

    # 定义发送邮件的内容，支持HTML和CSS样式
    content = f"<br/>欢迎注册蜗牛笔记博客系统账号，您的邮箱验证码为：" \
              f"<span style='color: red; font-size: 20px;'>{ecode}</span>, " \
              f"请复制到注册窗口完成注册"
    message = MIMEText(content, 'html', 'utf-8')  # 实例化邮件对象，并指定邮件的关键信息
    # 指定邮件的标题，同样使用utf-8编码
    message['Subject'] = Header('蜗牛笔记的注册验证码', 'utf-8')
    message['From'] = sender
    message['To'] = receiver

    smtpObj = SMTP_SSL('smtp.qq.com')  # 建议与QQ邮件服务器的链接
    smtpObj.login(user='xxxxxxxxx@qq.com', password='授权码')  # 通过自己的邮箱账号和获取到的授权码登录QQ邮箱

    # 指定发件人、收件人和邮件内容
    smtpObj.sendmail(sender, receiver, str(message))
    smtpObj.quit()


def gen_email_code():
    str = random.sample(string.ascii_letters + string.digits, 6)
    return ''.join(str)


def model_list(result):
    """单个模型类，转换为标准的python list数据"""
    list = []
    for row in result:
        dict = {}
        for k, v in row.__dict__.items():
            if not k.startswith('_sa_instance_state'):
                if isinstance(v, datetime):
                    v = v.strftime('%Y-%m-%d %H:%M:%S')
                dict[k] = v
        list.append(dict)
    return list


def model_join_list(result):
    """SQLAlchemy连接查询两张表的结果集转换[{},{}]"""
    list = []  # 定义列表用于存放所有行
    for obj1, obj2 in result:
        dict = {}
        for k1, v1 in obj1.__dict__.items():
            if not k1.startswith('_sa_instance_state'):
                if not k1 in dict:  # 如果字典中已经存在相同的key则跳过
                    dict[k1] = v1
        for k2, v2 in obj2.__dict__.items():
            if not k2.startswith('_sa_instance_state'):
                if not k2 in dict:  # 如果字典中已经存在相同的key则跳过
                    dict[k2] = v2
        list.append(dict)
    return list


def compress_image(source, dest, width):
    """
    压缩图片，通过参数width指定压缩后的图片大小
    :param source:
    :param dest:
    :param width:
    :return:
    """
    from PIL import Image

    # 如果图片宽度大于1200。则调整为1200的高度
    im = Image.open(source)
    x, y = im.size  # 获取源图片的宽高
    if x > width:
        # 等比例缩放
        ys = int(y * width / x)
        xs = width

        # 调整当前图片的尺寸（同时也会压缩大小）
        temp = im.resize((xs, ys), Image.ANTIALIAS)

        # 将图片保存并使用80%的质量进行压缩（继续压缩）
        temp.save(dest, quality=80)
    else:  # 如果尺寸小于指定宽度则不缩减尺寸，只压缩保存
        im.save(dest, quality=80)


def parse_image_url(content):
    """解析文章内容中的图片地址"""
    import re
    temp_list = re.findall('<img src="(.+?)"', content)
    url_list = []

    for url in temp_list:
        # 如果图片类型为gif，则直接跳过，不对其作任何处理
        if url.lower().endswith('.gif'):
            continue
        url_list.append(url)
    return url_list


def download_image(url, dest):
    """远程下载指定URL地址的图片，并保存到临时的目录中"""
    import requests
    response = requests.get(url)  # 获取图片的响应
    with open(file=dest, mode='wb') as file:
        file.write(response.content)


def generate_thumb(url_list):
    """解析列表中的图片URL地址并生成缩略图，返回缩略图名称"""
    # 根据URL地址解析出其文件名和域名
    # 通常建议使用文章内容中的第一张图片来生成所掳如图
    # 先遍历url_list，查找里面是否存在本地上床图片，找到即处理，代码运行结束
    for url in url_list:
        if url.startswith('/upload/'):
            filename = url.split('/')[-1]

            # 找到本地图片后对其进行压缩处理，设置缩略图宽度为400像素即可
            compress_image('./resource/upload/' + filename,
                           './resource/thumb/' + filename, 400)
            return filename

    # 如果没有找到本地图片，则需要先将网络图片下载到本地再作处理
    # 直接将第一张图片作为缩略图，并生成基于时间戳的标准文件名
    url = url_list[0]
    filename = url.split('/')[-1]
    suffix = filename.split('.')[-1]
    thumbname = time.strftime('%Y%m%d_%H%M%S.' + suffix)
    download_image(url, './resource/download/' + thumbname)
    compress_image('./resource/download/' + thumbname, './resource/thumb/' + thumbname, 400)

    return thumbname  # 返回当前缩略图的文件名


# 测试代码
# if __name__ == '__main__':
#     content = '''
#     <p>
#         啊飒飒
#     </p>
#     <p>
#         <img src="/upload/90b36e4a563bad8ba1cf55a21a456886.jpeg" title="90b36e4a563bad8ba1cf55a21a456886.jpeg" alt="90b36e4a563bad8ba1cf55a21a456886.jpeg"/>
#     </p>
#     <p>
#         asas
#     </p>
#     <p>
#         <img src="/upload/mmexport1561284889076.jpg" title="mmexport1561284889076.jpg" alt="mmexport1561284889076.jpg"/>
#     </p>
#     <p>
#         打发打发
#     </p>
#     <p>
#         <img src="https://woniufile.oss-cn-hangzhou.aliyuncs.com/banner/banner.com.pc%20(1).jpg"/>
#     </p>
#     '''
#
#     list = parse_image_url(content)
#     thumb = generate_thumb(list)
#     print(thumb)