import statistics
import tkinter
import time
from PIL import Image, ImageTk  # 外部ライブラリ
import pyautogui  # 外部ライブラリ
import cv2
import numpy as np
import os
from tqdm import tqdm
import threading

RESIZE_RATIO = 2 # 縮小倍率の規定
WIDTH = 1024
HEIGHT = 1280

class GuiApplication(tkinter.Frame):
    input_folder = None
    output_folder = None
    data_number = None
    data_name = None
    img_array = np.empty(1)
    resized_img_array = np.empty(1)
    start_x = -1
    start_y = -1
    end_x = -1
    end_y = -1

    def __init__(self, master=None):
        super().__init__(master)
        self.master.title('ColorChart')
        self.master.attributes("-topmost", True)
        self.create_window()

    def create_window(self):
        files = os.listdir("./Input/")
        self.data_name = [f for f in files if os.path.isfile(os.path.join("./Input/", f))]
        # print(self.data_name)
        self.data_number = 0
        self.img_array = np.empty([len(self.data_name), HEIGHT, WIDTH, 3], dtype=np.uint8)
        self.resized_img_array = np.empty([len(self.data_name), int(HEIGHT/RESIZE_RATIO), int(WIDTH/RESIZE_RATIO), 3], dtype=np.uint8)
        for i, name in enumerate(self.data_name):
            img_path = "./Input/" + name
            img = cv2.imread(img_path)
            copy_img = img.copy()
            img_resized = cv2.resize(copy_img, (int(WIDTH/RESIZE_RATIO), int(HEIGHT/RESIZE_RATIO)))
            self.img_array[i, :, :, :] = np.asarray(img)
            self.resized_img_array[i, :, :, :] = np.asarray(img_resized)


        # Canvasウィジェットの描画
        self.canvas1 = tkinter.Canvas(self.master,
                                 bg='black',
                                 width=WIDTH / RESIZE_RATIO,
                                 height=HEIGHT / RESIZE_RATIO)
        # Canvasウィジェットに取得した画像を描画
        # item = canvas1.create_image(0, 0, image=img_tk, anchor=tkinter.NW)
        # Canvasウィジェットを配置し、各種イベントを設定
        self.canvas1.pack()
        self.canvas1.bind("<ButtonPress-1>", self.start_point_get)
        self.canvas1.bind("<Button1-Motion>", self.rect_drawing)
        self.canvas1.bind("<ButtonRelease-1>", self.release_action)

        # ボタンの作成と配置
        self.button = tkinter.Button(
            self.master,
            text="補正",
            command=lambda: self.button_click()
        )
        self.button.pack()
        self.change_image()
        # root.mainloop()

# ドラッグ開始した時のイベント - - - - - - - - - - - - - - - - - - - - - - - - - -
    def start_point_get(self, event=None):
        # global start_x, start_y  # グローバル変数に書き込みを行なうため宣言

        self.canvas1.delete("rect1")  # すでに"rect1"タグの図形があれば削除

        # canvas1上に四角形を描画（rectangleは矩形の意味）
        self.canvas1.create_rectangle(event.x,
                                      event.y,
                                      event.x + 1,
                                      event.y + 1,
                                      outline="red",
                                      tag="rect1")
        # グローバル変数に座標を格納
        self.start_x, self.start_y = event.x, event.y

# ドラッグ中のイベント - - - - - - - - - - - - - - - - - - - - - - - - - -
    def rect_drawing(self, event=None):

        # ドラッグ中のマウスポインタが領域外に出た時の処理
        if event.x < 0:
            self.end_x = 0
        else:
            self.end_x = min(WIDTH / RESIZE_RATIO, event.x)
        if event.y < 0:
            self.end_y = 0
        else:
            self.end_y = min(HEIGHT / RESIZE_RATIO, event.y)

        # "rect1"タグの画像を再描画
        self.canvas1.coords("rect1", self.start_x, self.start_y, self.end_x, self.end_y)

# ドラッグを離したときのイベント - - - - - - - - - - - - - - - - - - - - - - - - - -
    def release_action(self, event=None):
        # global end_x, end_y

        # "rect1"タグの画像の座標を元の縮尺に戻して取得
        self.start_x, self.start_y, self.end_x, self.end_y = [
            round(n * RESIZE_RATIO) for n in self.canvas1.coords("rect1")
        ]

        # 取得した座標を表示
        # pyautogui.alert("start_x : " + str(self.start_x) + "\n" + "start_y : " +
        #                 str(self.start_y) + "\n" + "end_x : " + str(self.end_x) + "\n" +
        #                 "end_y : " + str(self.end_y))

    def button_click(self):
        if self.start_x < 0:
            pyautogui.alert("please select a black area")
        else:
            # print(path)
            # print(start_x*2, start_y*2, end_x, end_y)
            # 画素値の取得
            # pyautogui.alert("start_x : " + str(self.start_x) + "\n" + "start_y : " +
            #                 str(self.start_y) + "\n" + "end_x : " + str(self.end_x) + "\n" +
            #                 "end_y : " + str(self.end_y))
            image = self.img_array[self.data_number, :, :, :]
            out_path = "./Output/" + self.data_name[self.data_number]
            m = image[self.start_y:self.end_y, self.start_x:self.end_x]
            # cv2.imshow('window', m)
            # rsum, gsum, bsum = 0.0, 0.0, 0.0
            r_list = []
            g_list = []
            b_list = []
            for raster in m:
                for px in raster:
                    # rsum += px[2]
                    # gsum += px[1]
                    # bsum += px[0]
                    r_list.append(px[2])
                    g_list.append(px[1])
                    b_list.append(px[0])
            # 平均値
            # ravg = rsum / ((self.end_x - self.start_x) * (self.end_y - self.start_y))
            # gavg = gsum / ((self.end_x - self.start_x) * (self.end_y - self.start_y))
            # bavg = bsum / ((self.end_x - self.start_x) * (self.end_y - self.start_y))
            # print(bavg, gavg, ravg)

            #中央値
            # r_median = statistics.median(r_list)
            # g_median = statistics.median(g_list)
            # b_median = statistics.median(b_list)
            # print(b_median, g_median, r_median)

            # 最頻値
            r_mode = statistics.mode(r_list)
            g_mode = statistics.mode(g_list)
            b_mode = statistics.mode(b_list)
            # print(b_mode, g_mode, r_mode)

            h, w, c = image.shape
            copy_img = image.copy()
            cv2.rectangle(copy_img, (0, h - 210), (200, h), (int(b_mode), int(g_mode), int(r_mode)), thickness=-1)
            cv2.imwrite(out_path, copy_img)
            self.data_number = self.data_number + 1
            if self.data_number < len(self.data_name):
                self.change_image()
                self.start_x = -1
                self.start_y = -1
                self.end_x = -1
                self.end_y = -1

            else:
                pyautogui.alert("finished")
                self.master.destroy()


    def change_image(self):
        cv2_image = self.resized_img_array[self.data_number, :, :, :]
        # BGR(opencv) -> RGB(numpy) -> PIL image
        pil_image = Image.fromarray(cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB))

        # convert PIL.Image to PhotoImage
        self.photo_image = ImageTk.PhotoImage(image=pil_image)

        # display image to canvas
        self.update()
        self.canvas1.create_image(self.canvas1.winfo_width() // 2,
                                 self.canvas1.winfo_height() // 2,
                                 image=self.photo_image)

# メイン処理 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if __name__ == "__main__":
    root = tkinter.Tk()
    app = GuiApplication(master=root)
    app.mainloop()


