#!/usr/local/bin/python
# -*- coding: utf-8 -*-
"""
Created on Sep 17, 2020

@author: Carima
"""
import cv2
import numpy.core as np
from PIL import Image
import os
from xmlrpc import client
from multiprocessing import Process
import datetime
import logging.handlers
import threading
import time
from time import sleep


class lightThread(threading.Thread):

    def Layerpath(self, imagePath):
        self.imagePath = imagePath

    def run(self):
        os.system("omxiv -d 5 " + self.imagePath)
        return 1


class showslice():
    """
    classdocs
    """

    def __init__(self, imageRoot, fileType='gif', filter=False):
        """
        Constructor
        :param imageRoot: image folder path. no slash(/) at the end.
        :param fileType: gif, jpg, png, etc. no dot(.) at the beginning.
        """
        self.imageRoot = imageRoot
        self.fileType = fileType
        self.filter = filter
        self.imagesPath = os.environ.get('HOME', '/home/dp110') + '/carima/dp110server/images'
        # self.maskpath = os.environ.get('HOME', '/home/pi') + '/carima/basic/IM-J_basic/mask.png'
        # self.gridpath = os.environ.get('HOME', '/home/pi') + '/carima/basic/IM-J_basic'
        self.blackpath = os.environ.get('HOME', '/home/pi') + '/carima/dp110server/images/black4K.png'
        #         self.xmlrpcclient()
        self.proxy = client.ServerProxy("http://127.0.0.1:8181")

    def loadGif(self, imagePath):
        pimg = Image.open(imagePath).convert('RGB')
        oimg = np.array(pimg)
        if self.filter:
            kernel = np.ones((3, 3), np.float32) / 2
            return cv2.filter2D(oimg, -1, kernel)
        else:
            return oimg

    def xmlrpcclient(self):
        self.proxy = client.ServerProxy("http://127.0.0.1:8181")
        # QT와 xmlrpc 연결이 정상적으로 되어있다는 로직 추가 필요

    def showImgThread(self, imagePath):
        os.system("omxiv -d 2 " + imagePath)
        return True

    def showImgFlipThread(self, imagePath):
        os.system("omxiv -m -d 2 " + imagePath)
        return True

    def fourKlamp(self, OnOff):
        cv2.waitKey(1000)
        self.proxy.ui_lamp(OnOff)
        return True

    def showBlackImgThread(self, imagePath):
        #         self.Insertlog('blackImg process')
        th = Process(target=self.showImgThread, args=[imagePath])
        th.start()
        th.join(1)
        th.terminate()
        return True

    def closeImgThread(self):
        os.system("killall omxiv")
        return True

    def Timer(self, msec):
        nowTime = time()
        while 1:
            currnetTime = time()
            Timer = round(currnetTime - nowTime, 1)
            if Timer == msec:
                return 1

    def showSliceImage(self, imagePath, secs):  # omx or openCV
        self.proxy.ui_lamp(True)
        th = Process(target=self.showImgThread, args=[imagePath])
        th.start()

        # use openCV
        # img = cv2.imread(imagePath, cv2.IMREAD_COLOR)
        # cv2.imshow("main", img)
        # cv2.waitKey(50)
        if secs > 0:
            sleep(secs)
        return True

    def showSliceImage_nolamp(self, imagePath, secs):  # qt cleaning or enginecurrent call
        # self.proxy.ui_lamp(True)
        th = Process(target=self.showImgThread, args=[imagePath])
        th.start()
        if secs > 0:
            sleep(secs)
        return True

    def showGridSliceImage(self, imagePath, secs):
        self.proxy.ui_lamp(True)
        th = Process(target=self.showImgThread, args=[imagePath])
        th.start()
        if secs > 0:
            sleep(secs)
        return True

    def FlipshowSliceImage(self, imagePath, secs):
        #         self.proxy.ui_lamp(True)
        th = Process(target=self.showImgFlipThread, args=[imagePath])
        th.start()
        if secs > 0:
            sleep(secs)
        return True

    def showSlice4KImage(self, imagePath, secs):
        th = Process(target=self.showImgThread, args=[imagePath])
        th.start()
        if 0:   # no need about sleep 1 sec and lamp because treat in printThread_4K.py run func
            Lampth = Process(target=self.fourKlamp, args=[True])
            Lampth.start()
        if secs > 0:
            sleep(secs)
        return True

    def showBlackImage(self):
        self.proxy.ui_lamp(True)
        th = Process(target=self.showImgThread, args=[self.blackpath])
        th.start()
        return True

    def showSliceOffImage(self):
        sleep(0.17)
        th = Process(target=self.closeImgThread)
        th.start()
        # use openCV
        # cv2.destroyAllWindows()
        return True

    def clear(self):
        self.proxy.ui_lamp(False)
        cv2.waitKey(170)
        # self.proxy.EngineOffCall()
        # 블랙 이미지를 쏘기 전에 LED를 꺼주어야함.
        # self.showImage(self.imagesPath + '/black.png', 0)
        # self.showSliceImage(os.environ.get('HOME','/home/pi') + '/carima/dp110server/images/black.png', 0.1)
        th = Process(target=self.closeImgThread)
        th.start()
        th.join(1)
        return True

    def maskImageOn(self):
        # self.showSliceImage(os.environ.get('HOME','/home/pi') + '/carima/build-3DPrinter-Desktop-Release/basic/mask.png', -1)
        self.showSliceImage_nolamp(os.environ.get('HOME', '/home/pi') + '/carima/basic/mask_edit.png', -1)
        return True

    def FlipmaskImageOn(self):
        self.FlipshowSliceImage(os.environ.get('HOME', '/home/pi') + '/carima/basic/mask_edit.png', -1)
        return True

    def buildImageOn(self):
        self.showSliceImage(os.environ.get('HOME', '/home/pi') + '/carima/dp110server/images/build.png', -1)
        return True

    # def fixBuildImageOn(self):
    #     self.showSliceImage(os.environ.get('HOME', '/home/pi') + '/carima/dp110server/images/fixBuild.png', -1)
    #     return True

    def focusImageOn(self):
        # self.showSliceImage(os.environ.get('HOME','/home/pi') + '/carima/build-3DPrinter-Desktop-Release/dp110server/images/focus.png', -1)
        self.showSliceImage(os.environ.get('HOME', '/home/pi') + '/carima/basic/BasicImg_edit.png', -1)
        return True

    def whiteImageOn(self):
        self.showSliceImage(os.environ.get('HOME', '/home/pi') + '/carima/dp110server/images/white.png', 0)
        return True

    def whiteImageOn1280(self):
        self.showSliceImage(os.environ.get('HOME', '/home/pi') + '/carima/dp110server/images/white1280.png', 0)
        return True

    def gridImageOn(self):
        self.showGridSliceImage(os.environ.get('HOME', '/home/pi') + '/carima/Grid.png', -1)
        return True

    def whiteImageOff(self):
        self.showSliceImage(self.imagesPath + '/black.png', 0)
        self.showSliceOffImage()
        return True

    def setupGrids(self, xres, yres, xgrid, ygrid, line=5):
        # self.xres = 1920
        # self.yres = 1080
        # self.xgrid = 6
        # self.ygrid = 4
        # self.line = line
        # cv2.namedWindow("dp110display")
        # cv2.cv.ResizeWindow("dp110display", xres, yres)
        # cv2.cv.MoveWindow("dp110display", 1024, 0)
        # self.grid = np.zeros((yres, xres ,4), np.uint8)
        # self.white=(255,255,255,255)
        # self.black=(0,0,0,255)
        # self.xseg = 1920 / 6
        # self.yseg = 1080 / 4
        return 1

    # im2 code, why use 960, 540 instead of 2160, 3840 (FHD np.zeros((1080, 1920, 3)
    def makeGrids4K(self, x, y, val):
        color = (val, val, val, 255)
        self.grid = np.zeros((960, 540, 4), np.uint8)
        self.line = 5
        self.black = (0, 0, 0, 255)
        self.xseg = 960 / 6
        self.yseg = 540 / 4

        # 흰 이미지 그리기
        cv2.rectangle(self.grid, (x * self.xseg, y * self.yseg), ((x + 1) * self.xseg, (y + 1) * self.yseg), color, -1)
        # 블랙채우기
        cv2.rectangle(self.grid, (x * self.xseg, y * self.yseg), ((x + 1) * self.xseg, (y + 1) * self.yseg), self.black,
                      self.line)
        cv2.imwrite(os.environ.get('HOME', '/home/pi') + '/carima/grid.png', self.grid)
        return 1

    def makeGrids(self, x, y, val):
        color = (val, val, val, 255)
        self.grid = np.zeros((1080, 1920, 3), np.uint8)
        self.line = 5
        self.black = (0, 0, 0, 255)
        self.xseg = int(1920 / 6)
        self.yseg = int(1080 / 4)

        # 흰 이미지 그리기
        # cv2.circle(self.grid, (160, 135), 100, color, -1) #0,0
        # cv2.circle(self.grid, (480, 135), 100, color, -1) #1,0
        # cv2.circle(self.grid, (800, 135), 100, color, -1) #2,0
        # cv2.circle(self.grid, (1120, 135), 100, color, -1) #3,0
        # cv2.circle(self.grid, (1440, 135), 100, color, -1) #4,0
        # cv2.circle(self.grid, (1760, 135), 100, color, -1) #5,0
        #
        # cv2.circle(self.grid, (160, 405), 100, color, -1) #0,1
        # cv2.circle(self.grid, (480, 405), 100, color, -1) #1,1
        # cv2.circle(self.grid, (800, 405), 100, color, -1) #2,1
        # cv2.circle(self.grid, (1120, 405), 100, color, -1) #3,1
        # cv2.circle(self.grid, (1440, 405), 100, color, -1) #4,1
        # cv2.circle(self.grid, (1760, 405), 100, color, -1) #5,1
        #
        # cv2.circle(self.grid, (160, 675), 100, color, -1) #0,2
        # cv2.circle(self.grid, (480, 675), 100, color, -1) #1,2
        # cv2.circle(self.grid, (800, 675), 100, color, -1) #2,2
        # cv2.circle(self.grid, (1120, 675), 100, color, -1) #3,2
        # cv2.circle(self.grid, (1440, 675), 100, color, -1) #4,2
        # cv2.circle(self.grid, (1760, 675), 100, color, -1) #5,2
        #
        # cv2.circle(self.grid, (160, 945), 100, color, -1) #0,3
        # cv2.circle(self.grid, (480, 945), 100, color, -1) #1,3
        # cv2.circle(self.grid, (800, 945), 100, color, -1) #2,3
        # cv2.circle(self.grid, (1120, 945), 100, color, -1) #3,3
        # cv2.circle(self.grid, (1440, 945), 100, color, -1) #4,3
        # cv2.circle(self.grid, (1760, 945), 100, color, -1) #5,3

        cv2.rectangle(self.grid, (x * self.xseg, y * self.yseg), ((x + 1) * self.xseg, (y + 1) * self.yseg), color, -1)
        # 블랙채우기
        cv2.rectangle(self.grid, (x * self.xseg, y * self.yseg), ((x + 1) * self.xseg, (y + 1) * self.yseg), self.black, self.line)

        cv2.imwrite(os.environ.get('HOME', '/home/pi') + '/carima/Grid.png', self.grid)
        return 1

    def makeGrids1280(self, x, y, val):
        color = (val, val, val, 255)
        self.grid = np.zeros((1280, 800, 4), np.uint8)
        self.line = 5
        self.black = (0, 0, 0, 255)
        self.xseg = 1280 / 6
        self.yseg = 800 / 4

        # 흰 이미지 그리기
        cv2.rectangle(self.grid, (x * self.xseg, y * self.yseg), ((x + 1) * self.xseg, (y + 1) * self.yseg), color, -1)
        # 블랙채우기
        cv2.rectangle(self.grid, (x * self.xseg, y * self.yseg), ((x + 1) * self.xseg, (y + 1) * self.yseg), self.black, self.line)
        cv2.imwrite(os.environ.get('HOME', '/home/pi') + '/carima/grid.png', self.grid)

        return 1

    def clearGrids(self):
        self.showImage(self.imagesPath + '/black.png', 0)
        self.grid[:] = self.black = (0, 0, 0, 225)
        return 1

    def Insertlog(self, logmsg):
        now = datetime.datetime.now()
        # if datetime is changed, filename will be changed
        # if date or time has been changed, handler will be removed and create new filehandler for a new file name...shit...
        if (self.logtime != now.strftime('%d-%H')):
            self.logbytime.removeHandler(self.logbytime.handlers[0])
            self.Initlog()
        self.logbytime.info(logmsg)  # the Message is written in file

    def Initlog(self):
        # 년월에 해당하는 폴더가 생성되어 있는지 먼저 파악 -> 매번 해당 루틴을 수행하는 은 좋지 않다. 처음 프린터가 실행되었을 때만 확인
        now = datetime.datetime.now()
        nowDateYM = now.strftime(os.environ.get('HOME', '/home/pi') + '/SystemLog/%Y-%m')
        # nowDateYM=now.strftime('./SystemLog/%Y-%m')
        if not os.path.exists(nowDateYM):
            os.makedirs(nowDateYM)
        self.logtime = now.strftime('%d-%H')
        nowDateMDH = now.strftime(os.environ.get('HOME', '/home/pi') + '/SystemLog/%Y-%m/%m-%d-%H')
        # nowDateMDH=now.strftime('./SystemLog/%Y-%m/%m-%d-%H')
        self.logbytime = logging.getLogger('imjlog')
        hdlr = logging.handlers.TimedRotatingFileHandler(nowDateMDH)
        # formatter = logging.Formatter('[%(asctime)s] %(funcName)s', datefmt='%I:%M:%S')
        formatter = logging.Formatter('[%(asctime)s] %(message)s', datefmt='%H:%M:%S')
        hdlr.setFormatter(formatter)
        self.logbytime.addHandler(hdlr)
        self.logbytime.setLevel(logging.INFO)
