# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import math
import numpy as np
from PIL import Image


def checkOpenGrid(img, thumbnail_min):
    H, W = img.shape[:2]
    if max(H, W) <= thumbnail_min:
        return False
    else:
        return True


class Grids:
    def __init__(self, img, gridSize=(512, 512), overlap=(24, 24)):
        self.clear()
        self.detimg = img
        self.gridSize = np.array(gridSize)
        self.overlap = np.array(overlap)

    def clear(self):
        # 图像HWC格式
        self.detimg = None  # 宫格初始图像
        self.grid_init = False  # 是否初始化了宫格
        # self.imagesGrid = []  # 图像宫格
        self.mask_grids = []  # 标签宫格
        self.json_labels = []  # 保存标签
        self.grid_count = None  # (row count, col count)
        self.curr_idx = None  # (current row, current col)

    def createGrids(self):
        # 计算宫格横纵向格数
        imgSize = np.array(self.detimg.shape[:2])
        grid_count = np.ceil((imgSize + self.overlap) / self.gridSize)
        self.grid_count = grid_count = grid_count.astype("uint16")
        # ul = self.overlap - self.gridSize
        # for row in range(grid_count[0]):
        #     ul[0] = ul[0] + self.gridSize[0] - self.overlap[0]
        #     for col in range(grid_count[1]):
        #         ul[1] = ul[1] + self.gridSize[1] - self.overlap[1]
        #         lr = ul + self.gridSize
        #         # print("ul, lr", ul, lr)
        #         # 扩充
        #         det_tmp = self.detimg[ul[0]: lr[0], ul[1]: lr[1]]
        #         tmp = np.zeros((self.gridSize[0], self.gridSize[1], self.detimg.shape[-1]))
        #         tmp[:det_tmp.shape[0], :det_tmp.shape[1], :] = det_tmp
        #         self.imagesGrid.append(tmp)
        # self.mask_grids = [[np.zeros(self.gridSize)] * grid_count[1]] * grid_count[0]  # 不能用浅拷贝
        self.mask_grids = [
            [np.zeros(self.gridSize) for _ in range(grid_count[1])]
            for _ in range(grid_count[0])
        ]
        # print(len(self.mask_grids), len(self.mask_grids[0]))
        self.grid_init = True
        return list(grid_count)

    def getGrid(self, row, col):
        gridIdx = np.array([row, col])
        ul = gridIdx * (self.gridSize - self.overlap)
        lr = ul + self.gridSize
        img = self.detimg[ul[0]:lr[0], ul[1]:lr[1]]
        mask = self.mask_grids[row][col]
        self.curr_idx = (row, col)
        return img, mask

    def splicingList(self, save_path):
        """
        将slide的out进行拼接，raw_size保证恢复到原状
        """
        imgs = self.mask_grids
        raw_size = self.detimg.shape[:2]
        # h, w = None, None
        # for i in range(len(imgs)):
        #     for j in range(len(imgs[i])):
        #         im = imgs[i][j]
        #         if im is not None:
        #             h, w = im.shape[:2]
        #             break
        # if h is None and w is None:
        #     return False
        h, w = self.gridSize
        row = math.ceil(raw_size[0] / h)
        col = math.ceil(raw_size[1] / w)
        result_1 = np.zeros((h * row, w * col), dtype=np.uint8)
        result_2 = result_1.copy()
        # k = 0
        for i in range(row):
            for j in range(col):
                ih, iw = imgs[i][j].shape[:2]
                im = np.zeros(self.gridSize)
                im[:ih, :iw] = imgs[i][j]
                start_h = (i * h) if i == 0 else (i * (h - self.overlap[0]))
                end_h = start_h + h
                start_w = (j * w) if j == 0 else (j * (w - self.overlap[1]))
                end_w = start_w + w
                # 单区自己，重叠取或
                if (i + j) % 2 == 0:
                    result_1[start_h:end_h, start_w:end_w] = im
                else:
                    result_2[start_h:end_h, start_w:end_w] = im

        result = np.where(result_2 != 0, result_2, result_1)
        result = result[:raw_size[0], :raw_size[1]]
        Image.fromarray(result).save(save_path, "PNG")
        return result
