import json
import os
from module.view_control.generate_goods_no_detail_pic.pic_deal import PictureProcessing
from PIL import Image
import shutil
from module.base_mode.base import get_images, check_path, get_image_mask
from natsort import ns, natsorted
import math
from PIL import ImageFont
import settings


class DetailBase(object):
    def __init__(self, goods_no, goods_no_value: dict, out_put_dir, windows=None, excel_data=None,
                 assigned_page_list=None):
        self.goods_no = goods_no
        self.out_put_dir = out_put_dir
        self.deal_pic_func_list = []
        self.goods_no_value = goods_no_value
        self.root = ""
        self.windows = windows
        print(goods_no_value)
        # 重新解析为新的数据结构
        self.data = {}
        self.detailed_images = []
        self.assigned_page_list = assigned_page_list
        self.overlay_pic_dict = {}
        self.init()
        # for goods_art_no_dict in self.goods_no_value["货号资料"]:
        #     print(goods_art_no_dict)
        #
        # raise 1

        if excel_data:
            ig_keys = ["模板名称"]
            for k, v in excel_data.items():
                if k not in ig_keys:
                    self.goods_no_value[k] = v

    def run_all(self):
        print("===================detailed_images=================")
        detailed_images = self.deal_details()
        self.create_folder(self.out_put_dir)
        detail_path = "{out_put_dir}/{goods_no}/details".format(out_put_dir=self.out_put_dir, goods_no=self.goods_no)
        self.create_folder(detail_path)
        self.save_to_png(detailed_images=detailed_images, detail_path=detail_path)
        # 生成拼接图
        self.generate_spliced_picture()

        # ------------移动其他图片---------------------
        # 获取主图模板列表
        main_pic_path_list = DetailBase.get_temp_pic_info(root=self.root)["main_pic_path_list"]
        if not main_pic_path_list:
            self.move_other_pic(move_main_pic=True)
        else:
            self.move_other_pic(move_main_pic=True)
            if not self.assigned_page_list:
                self.deal_all_main_pic()
            else:
                if "主图" in self.assigned_page_list:
                    self.deal_all_main_pic()
        return True

    # 生成各个详情图切片
    def deal_details(self):
        detailed_images = []
        for index, func in enumerate(self.deal_pic_func_list):
            if not self.assigned_page_list:
                self.image_list_append(detailed_images, func())
            else:
                index = "{}".format(index + 1)
                if index in self.assigned_page_list:
                    self.image_list_append(detailed_images, func())
                else:
                    self.image_list_append(detailed_images, {"mes": "不生成"})
        return [x for x in detailed_images if x]

    # 生成拼接的图片
    def generate_spliced_picture(self):
        detail_path = "{out_put_dir}/{goods_no}/details".format(out_put_dir=self.out_put_dir, goods_no=self.goods_no)
        if not os.path.exists(detail_path):
            return
        detailed_images = []
        for image_data in get_images(detail_path):
            detailed_images.append(PictureProcessing(image_data["file_path"]))
        # 生成拼接图
        img = self.add_pic(detailed_images)
        join_path = "{out_put_dir}/{goods_no}/拼接图".format(out_put_dir=self.out_put_dir, goods_no=self.goods_no)
        self.create_folder(join_path)
        img.save("{}/1.jpg".format(join_path), format="JPEG")

    def image_list_append(self, image_list: list, data):
        self.check_state_end()
        image_list.append(data)

    def save_to_png(self, detailed_images, detail_path):
        self.check_state_end()
        for index, pp in enumerate(detailed_images):
            if isinstance(pp, dict):
                continue
            pp.im.save("{}/{}（{}）.png".format(detail_path, self.goods_no, str(index + 11).zfill(2)))

    def check_state_end(self):
        if self.windows is not None:
            if self.windows.state == 99:
                raise "用户主动取消"

    @classmethod
    def get_temp_pic_info(cls, root):
        """
        获取详情页模板中的信息
        """
        main_pic_list = []
        mask_pic_list = []
        if os.path.exists(r"{}\main_image".format(root)):
            for _name in os.listdir(r"{}\main_image".format(root)):
                _path = r"{}\main_image\{}".format(root, _name)
                if os.path.isdir(_path):
                    main_pic_list.append([x["file_path"] for x in get_images(_path)])
                    mask_pic_list.append(
                        [x["file_path"] for x in get_image_mask(_path)]
                    )
        _l = get_images(r"{}\show".format(root))
        temp_pic_path = _l[0]["file_path"] if _l else None

        other_pic_list = [x["file_path"] for x in get_images(r"{}".format(root))]
        return {
            "main_pic_path_list": main_pic_list,
            "temp_pic_path": temp_pic_path,
            "mask_pic_list": mask_pic_list,
            "other_pic_path_list": other_pic_list,
        }

    def init(self):
        for goods_art_no_value in self.goods_no_value["货号资料"]:
            self.data[goods_art_no_value["货号"]] = {"pics": goods_art_no_value["pics"],
                                                   "pic_is_deal": {}
                                                   }

    def get_text_value(self, key, subsection_len=0):
        text = ""
        if key in self.goods_no_value:
            if self.goods_no_value[key]:
                text = str(self.goods_no_value[key])
                text = text.replace(r"\n", "\n")

        if key in ["跟高", "鞋宽", "帮高", "脚掌围", "鞋长"]:
            if text:
                text = text.split(".")[0]

        if subsection_len != 0:
            text = text.split("\n")
            text = [x for x in text if x]
            if len(text) == 2:
                text_1 = text[0]
                text_2 = text[1]
                return text_1, text_2
            else:
                if text:
                    text_1 = text[0]
                else:
                    text_1 = ""
                text_2 = ""
                return text_1, text_2

        return text

    def create_folder(self, path):
        if not os.path.exists(path):
            os.makedirs(path)

    def get_all_process_pics(self):
        """
        获取所有颜色的过程图片
        data = [
            {"货号": "",
             "素材": [{
                 "名称": "俯视",
                 "抠图": "路径1",
                 "阴影": "路径2"
             }, ]},
        ]
        """
        return_data = []
        for goods_art_no in self.data:
            goods_art_no_dict = {"货号": goods_art_no,
                                 "素材": [],
                                 }

            # 图片数据重新排序
            pic_data = []
            for pic_name, pic_path in self.data[goods_art_no]["pics"].items():
                root_path, file_name = os.path.split(pic_path)
                pic_data.append(file_name)

            pic_data = natsorted(pic_data, alg=ns.PATH)

            for file_name in pic_data:
                if "阴影" in file_name:
                    _, action_name, _ = file_name.split("_")
                    pic_path = self.data[goods_art_no]["pics"]["{}-阴影".format(action_name)]
                    pic_cutout_path = self.data[goods_art_no]["pics"]["{}-抠图".format(action_name)]
                    if os.path.exists(pic_path) and os.path.exists(pic_cutout_path):
                        goods_art_no_dict["素材"].append({"名称": action_name, "抠图": pic_cutout_path, "阴影": pic_path})
            return_data.append(goods_art_no_dict)

        return return_data

    def get_overlay_pic_from_dict(self, goods_art_no, color_name, bg_color) -> PictureProcessing:
        self.check_state_end()
        # 增加逻辑，获取任意货号下的组合图
        if "组合" in color_name:
            goods_art_no, color_name = self.get_all_scene_list(goods_art_no, color_name)

        key = "{}-{}-{}".format(goods_art_no, color_name, bg_color)
        if key in self.overlay_pic_dict:
            return self.overlay_pic_dict[key]

        if goods_art_no in self.data:
            for pic_name, pic_path in self.data[goods_art_no]["pics"].items():
                if "阴影" in pic_name:
                    action_name = pic_name.replace("-阴影", "")
                    if action_name == color_name:
                        pp1 = PictureProcessing(pic_path)
                        pp2 = PictureProcessing(self.data[goods_art_no]["pics"]["{}-抠图".format(action_name)])
                        pp1 = pp1.get_overlay_pic(top_img=pp2, color=bg_color).resize(mode="pixel", base="width",
                                                                                      value=1600)
                        self.overlay_pic_dict[key] = pp1

        if key in self.overlay_pic_dict:
            return self.overlay_pic_dict[key]

    def image_init(self, bg_color=(246, 246, 246)):
        # 制作一批素材图，添加背景色，并保留阴影，以及处理成最小尺寸
        for goods_art_no in self.data:
            for pic_name, pic_path in self.data[goods_art_no]["pics"].items():
                if "阴影" in pic_name:
                    action_name = pic_name.replace("-阴影", "")
                    pp1 = PictureProcessing(pic_path)
                    pp2 = PictureProcessing(self.data[goods_art_no]["pics"]["{}-抠图".format(action_name)])
                    pp1 = pp1.get_overlay_pic(top_img=pp2, color=bg_color).resize(mode="pixel", base="width",
                                                                                  value=1600)
                    self.data[goods_art_no]["pic_is_deal"][action_name] = pp1

    # 获取任意货号的场景图,优先取指定货号；
    # 调整，按顺序从货号列表中提取所有组合图
    def get_all_scene_info(self, goods_art_no):
        data = []
        # 收集所有组合图
        # 找任意一个有组合图的货号
        for goods_art_no_dict in self.goods_no_value["货号资料"]:
            _goods_art_no = goods_art_no_dict["货号"]
            _view_name_list = set([x.split("-")[0] for x in goods_art_no_dict["pics"]])
            for _view_name in _view_name_list:
                if "组合" not in _view_name:
                    continue
                return _goods_art_no
        return goods_art_no

    def get_all_scene_list(self, goods_art_no, view_name: str):
        if "组合" == view_name:
            view_name = "组合1"
        try:
            view_index = int(view_name.replace("组合", "")) - 1
        except:
            return goods_art_no, "无法匹配"

        data = []
        # 收集所有组合图
        # 找任意一个有组合图的货号
        for goods_art_no_dict in self.goods_no_value["货号资料"]:
            _goods_art_no = goods_art_no_dict["货号"]
            _view_name_list = set([x.split("-")[0] for x in goods_art_no_dict["pics"]])
            for _view_name in _view_name_list:
                if "组合" not in _view_name:
                    continue
                data.append(
                    {"goods_art_no": _goods_art_no,
                     "view_name": _view_name
                     }
                )

        if len(data) <= view_index:
            return goods_art_no, "无法匹配"
        else:
            return data[view_index]["goods_art_no"], data[view_index]["view_name"]

    def image_one_pic(self, goods_art_no, name, bg_color=None, return_orign=None):
        # 增加逻辑，获取任意货号下的组合图
        if "组合" in name:
            goods_art_no, name = self.get_all_scene_list(goods_art_no, name)

        # 制作一批素材图，添加背景色，并保留阴影，以及处理成最小尺寸
        for pic_name, pic_path in self.data[goods_art_no]["pics"].items():
            if "阴影" in pic_name:
                action_name = pic_name.replace("-阴影", "")
                if name != action_name:
                    continue
                pp1 = PictureProcessing(pic_path)
                pp2 = PictureProcessing(self.data[goods_art_no]["pics"]["{}-抠图".format(action_name)])
                if not return_orign:
                    pp1 = pp1.get_overlay_pic(top_img=pp2, color=bg_color).resize(mode="pixel", base="width",
                                                                                  value=1600)
                    return pp1
                else:
                    return pp1, pp2

        if not return_orign:
            return None
        else:
            return None, None

    def move_other_pic(self, move_main_pic=True):
        # ------------------------------移动其他图片------------------------------
        goods_no_main_pic_number = 0
        for goods_art_no_dict in self.goods_no_value["货号资料"]:
            if "800x800" not in goods_art_no_dict:
                continue
            if not goods_art_no_dict["800x800"]:
                continue

            goods_art_no = ""
            if "编号" in goods_art_no_dict:
                if goods_art_no_dict["编号"]:
                    goods_art_no = goods_art_no_dict["编号"]
            if not goods_art_no:
                goods_art_no = goods_art_no_dict["货号"]
            # print("goods_art_no:", goods_art_no)
            # 移动颜色图=====================
            goods_art_no_f = "{}/{}/{}".format(self.out_put_dir, self.goods_no, goods_art_no)
            self.create_folder(goods_art_no_f)
            # 放入一张主图
            old_pic_path_1 = goods_art_no_dict["800x800"][0]
            shutil.copy(old_pic_path_1,
                        "{}/{}{}".format(goods_art_no_f, goods_art_no, os.path.splitext(old_pic_path_1)[1]))

            # 把其他主图放入作为款号图=====================
            if move_main_pic:
                for pic_path in goods_art_no_dict["800x800"]:
                    goods_no_main_pic_number += 1
                    e = os.path.splitext(pic_path)[1]
                    shutil.copy(pic_path,
                                "{out_put_dir}/{goods_no}/{goods_no}（{goods_no_main_pic_number}）{e}".format(
                                    out_put_dir=self.out_put_dir, goods_no=self.goods_no,
                                    goods_no_main_pic_number=str(goods_no_main_pic_number + 10).zfill(2),
                                    e=e))

    def deal_all_main_pic(self):
        """
        处理主图模板，如存在出图模板则进行对应处理
        """
        # 获取主图模板列表
        all_main_pic_path_list = DetailBase.get_temp_pic_info(root=self.root)["main_pic_path_list"]
        if not all_main_pic_path_list:
            return
        mask_pic_list = DetailBase.get_temp_pic_info(root=self.root)["mask_pic_list"]
        data = self.get_all_process_pics()
        print("========deal_all_main_pic=========主图相关素材：")

        view_list = ["组合", "组合2", "组合3", "组合4", "组合5", "组合6", "俯视", "侧视", "后跟", "鞋底", "内里", ]

        for _index, main_pic_path_list in enumerate(all_main_pic_path_list):
            self.check_state_end()
            out_path_root = "{out_put_dir}/{goods_no}/main_image_{_index}".format(
                out_put_dir=self.out_put_dir,
                goods_no=self.goods_no,
                _index=_index
            )
            check_path(out_path_root)
            if mask_pic_list[_index]:
                mask_pic = mask_pic_list[_index][0]
            else:
                mask_pic = None
            goods_no_main_pic_number = 10
            # g_index 为第几个颜色货号
            for g_index, goods_art_no_dict in enumerate(data):
                goods_art_no = goods_art_no_dict["货号"]
                # =====================重新指定=================================
                _material_sort_dict = {}
                for index, material_dict in enumerate(goods_art_no_dict["素材"]):
                    name = material_dict["名称"]
                    _material_sort_dict[name] = material_dict

                # ======================================================
                file_name_index = -1
                for view_name in view_list:
                    # 组合图比较特殊，为全局获取
                    if g_index != 0:
                        if "组合" in view_name:
                            continue

                    if view_name not in _material_sort_dict:
                        continue
                    self.check_state_end()
                    pp_jpg, pp_png = self.image_one_pic(goods_art_no, view_name, bg_color=None, return_orign=True)
                    if not pp_jpg:
                        continue

                    file_name_index += 1
                    # 获取对应主图模板
                    if len(main_pic_path_list) < file_name_index + 1:
                        main_pic_path = main_pic_path_list[-1]
                    else:
                        main_pic_path = main_pic_path_list[file_name_index]
                    pp_bg = PictureProcessing(main_pic_path)
                    original_width = pp_bg.width

                    if original_width != 1600:
                        pp_bg = pp_bg.resize(value=1600)

                    if mask_pic:
                        mask_bg = PictureProcessing(mask_pic)
                        mask_bg = mask_bg.resize(value=1600)
                        mask_box_im = mask_bg.get_im()
                        box_size = mask_box_im.getbbox()
                        result_image = mask_box_im.crop(box_size)
                        mask_width, mask_height = result_image.size
                        mask_x, mask_y = box_size[0], box_size[1]
                    else:
                        mask_width, mask_height = pp_bg.size
                        mask_width, mask_height = int(mask_width * 12 / 16), int(mask_height * 12 / 16)
                        mask_x, mask_y = int((pp_bg.size[0] - mask_width) / 2), int((pp_bg.size[1] - mask_height) / 2)

                    if view_name != "后跟":
                        pp_jpg = pp_jpg.resize(base_by_box=(mask_width, mask_height))
                        pp_png = pp_png.resize(base_by_box=(mask_width, mask_height))

                        # 计算粘贴的位置 mask的位置+图片在mask中的位置
                        p_x = mask_x + int((mask_width - pp_jpg.width) / 2)
                        p_y = mask_y + int((mask_height - pp_jpg.height) / 2)
                        pp_bg = pp_bg.to_overlay_pic_advance(mode="pixel", top_img=pp_jpg, base="nw",
                                                             value=(p_x, p_y), top_png_img=pp_png)
                    else:
                        new_mask_width, new_mask_height = int(mask_width / 1.6), int(mask_height / 1.6)

                        pp_jpg = pp_jpg.resize(base_by_box=(new_mask_width, new_mask_height))
                        pp_png = pp_png.resize(base_by_box=(new_mask_width, new_mask_height))
                        new_mask_x = int((mask_width - new_mask_width) / 2 + mask_x)
                        new_mask_y = int((mask_height - new_mask_height) / 2 + mask_y)

                        # 计算粘贴的位置 mask的位置+图片在mask中的位置
                        p_x = new_mask_x + int((new_mask_width - pp_jpg.width) / 2)
                        p_y = new_mask_y + int((new_mask_height - pp_jpg.height) / 2)

                        pp_bg = pp_bg.to_overlay_pic_advance(mode="pixel", top_img=pp_jpg, base="nw", value=(p_x, p_y),
                                                             top_png_img=pp_png)

                    goods_no_main_pic_number += 1
                    out_pci_mode = "." + settings.getSysConfigs(
                        "basic_configs", "image_out_format", "png"
                    )
                    out_pic_path = "{out_path_root}/{goods_no}（{goods_no_main_pic_number}）{pic_mode}".format(
                        out_path_root=out_path_root,
                        goods_no=self.goods_no,
                        goods_no_main_pic_number=goods_no_main_pic_number,
                        pic_mode=out_pci_mode,
                    )
                    out_pci_factor = float(
                        1
                        if settings.getSysConfigs(
                            "basic_configs", "image_sharpening", "1"
                        )
                        == ""
                        else settings.getSysConfigs(
                            "basic_configs", "image_sharpening", "1"
                        )
                    )
                    if out_pci_factor > 1.0:
                        print("图片锐化处理")
                        pp_bg = pp_bg.sharpen_image(factor=out_pci_factor)

                    if original_width < 1600:
                        pp_bg = pp_bg.resize(value=original_width)

                    print("392  out_pic_path", out_pic_path)
                    if out_pci_mode == ".jpg":
                        pp_bg.save_as_rgb(out_pic_path)
                    else:
                        pp_bg.save_as_png(out_pic_path)

    def add_pic(self, detailed_images):
        self.check_state_end()
        detailed_images = [x for x in detailed_images if x]
        if not detailed_images:
            return
        page_len = 0

        for index, pp in enumerate(detailed_images):
            page_len += pp.height

        bg_im = Image.new("RGB", (pp.width, page_len), (255, 255, 255))
        n = 0

        for index, pp in enumerate(detailed_images):
            bg_im.paste(pp.im, (0, n))
            n += pp.height
        return bg_im

    # 通用方法，用于写文字
    def add_text_list(self, text_list, spacing=5, base="wn"):
        text_list = [x for x in text_list if x["text"]]
        # print(text_list)
        # spacing 行间距
        text_image_list = []
        max_w = 0
        total_h = 0

        for text_data in text_list:
            _pp = PictureProcessing("RGBA", (1200, 800), (255, 255, 255, 0))
            if base == "wn" or base == "nw":
                align = "left"
                anchor = None
                value = (0, 200)
            if base == "cn" or base == "nc":
                align = "center"
                anchor = "mm"
                value = (600, 200)
            if base == "en" or base == "ne":
                align = "right"
                anchor = "rs"
                value = (1200, 200)

            _pp = _pp.get_text_image_advanced(
                value=value,
                font=text_data["font"],
                text=text_data["text"],
                align=align,
                anchor=anchor,
                spacing=5,
                fill=text_data["fill"],
                return_mode="min_image",
                margins=(0, 0, 0, 0)
            )
            text_image_list.append(_pp)
            if _pp.width > max_w:
                max_w = _pp.width

            total_h += _pp.height
            if "spacing" in text_data:
                total_h += text_data["spacing"]

        if not text_image_list:
            return None
        #
        bg = PictureProcessing("RGBA", (max_w, total_h * 3), (0, 0, 0, 0))
        y = 0
        for text_image, text_data in zip(text_image_list, text_list):
            bg = bg.paste_img(top_img=text_image, value=(0, y), base=base)
            y += spacing + text_image.height
            if "spacing" in text_data:
                y += text_data["spacing"]

        bg = bg.crop(mode="min")
        # _ = bg.paste_img_invert(top_img=PictureProcessing("RGB", (bg.width,bg.height), (255, 255, 255)))
        # _.show()
        return bg

    def generate_font_list_to_pic(self):

        font_path_list = [r"resources\ttf\puhui\Bold.ttf",
                          r"resources\ttf\puhui\Medium.ttf",
                          r"resources\ttf\puhui\Heavy.ttf",
                          r"resources\ttf\puhui\Light.ttf",
                          r"resources\ttf\puhui\Regular.ttf",
                          ]
        text_v_list = [
            "这是一段话Bold",
            "这是一段话Medium",
            "这是一段话Heavy",
            "这是一段话Light",
            "这是一段话Regular",
        ]
        detailed_images = []
        for font_path, text in zip(font_path_list, text_v_list):
            text_list = []
            for size in range(26, 80, 2):
                font = ImageFont.truetype(font_path, size)
                text_list.append({"text": "{}-字号{}".format(text, size),
                                  "font": font,
                                  "fill": (110, 110, 110),
                                  })
            text_image = self.add_text_list(text_list, spacing=15, base="nw")
            text_image = text_image.crop(mode="min")
            text_image = text_image.paste_img_invert(top_img=PictureProcessing("RGB", text_image.size, (255, 255, 255)))
            detailed_images.append(text_image)
        return PictureProcessing(im=self.add_pic(detailed_images))
