import os

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

import UtilPack as util

# EXIF 데이터에서 사진이 찍힌 날자와 시간을 가져온다
def GetDateInfo(ImgPath):
    img = _imageOpen(ImgPath)
    if None == img:
        return "", 0.0, 0.0
    
    dataEXIF = _getEXIFData(img)
    date = _getDateEXIF(dataEXIF)
    dataGPS = _parseGPSInfo(dataEXIF)
    lat, lon = _getlatlon(dataGPS)
    
    return date, lat, lon

def ProcessImg(imgAbsPath, fRatio, nQlt = 85, bOrientApy = True):
    #
    dirSave = "Thumb"
    dirpath, filename = os.path.split(imgAbsPath)
    parenDir = os.path.dirname(dirpath)
    dirThumb = os.path.join(parenDir, dirSave)
    finalPath = os.path.join(dirThumb, filename)
    
    # 설정은 상관없이 이전에 리사이즈 해 둔 것이 있으면 경로 반환
    if True == os.path.exists(finalPath):
        #print(f"[] -> {finalPath}")
        return finalPath

    img = _imageOpen(imgAbsPath)
    if None == img:
        return imgAbsPath
        
    nRotate = 0
    if True ==  bOrientApy:
        dataEXIF = _getEXIFData(img)
        nRotate = _getOrientationEXIF(dataEXIF)
    
    img = _rotateImg(img, nRotate)
    img = _resizeImg(img, fRatio)
    
    if False == os.path.exists(dirThumb):
        os.makedirs(dirThumb, 0o777)
        print(f"Thumb folder Created : {dirThumb}")
    
    img.save(finalPath, optimize=True, quality=nQlt)
    
    #print(f"{imgAbsPath} -> {finalPath}")
    
    return finalPath

def _rotateImg(imgSrc, nRotate):
    if None == imgSrc:
        return imgSrc
    
    if not isinstance(imgSrc, Image.Image):
        #raise TypeError("Input must be a PIL Image object")
        print("Type Error")
        return imgSrc
    
    if 0 >=  nRotate or 360 <= nRotate:
        return imgSrc
    
    imgRet = imgSrc.rotate(nRotate, expand=True)

    bbox = imgRet.getbbox()
    imgRet = imgRet.crop(bbox)
    
    return imgRet

def _resizeImg(imgSrc, fRatio ):
    if None == imgSrc:
        return imgSrc
    
    if not isinstance(imgSrc, Image.Image):
        #raise TypeError("Input must be a PIL Image object")
        return imgSrc
    
    if 0 >= fRatio or 1.0 < fRatio:
        return imgSrc
    
    imgRet = imgSrc.resize((int(imgSrc.width * fRatio), int(imgSrc.height * fRatio)))
    return imgRet

def _imageOpen(ImgPath):
    imgRet = None
    try:
        # 이미지 열기 시도
        imgRet = Image.open(ImgPath)
        imgRet.load()  # 이미지 파일을 실제로 로드하여 확인
    
        util.DbgOut("Image open successful")
        # 이미지 처리 코드 추가
    except FileNotFoundError:
        util.DbgOut(f"can't find Image': {ImgPath}")
    except OSError:
        util.DbgOut(f"Image broken or unsupported MIME: {ImgPath}")
    except Exception as e:
        util.DbgOut(f"unexpected error: {e}")
        
    return imgRet
    
# 이미지에서 EXIF 데이터를 추출하여 딕셔너리 형태로 반환
def _getEXIFData(image):
    exif_data = {}
    try:
        info = image._getexif()
        if info:
            for tag, value in info.items():
                decoded = TAGS.get(tag, tag)
                exif_data[decoded] = value
    except AttributeError:
        pass

    return exif_data

def _getDateEXIF(exif_data):
    date_taken = exif_data.get('DateTimeOriginal')
    return date_taken

# 0 : NoData
# 1: "Landscape (normal) -> 0"
# 3: "Landscape (upside down) -> 180"
# 6: "Portrait (rotated 90° CW) -> 270"
# 8: "Portrait (rotated 90° CCW) -> 90"
def _getOrientationEXIF(exif_data):  
    if exif_data is None:
        return 0
    
    retValue = 0
    # EXIF 태그에서 Orientation 추출
    for tag, value in exif_data.items():
        tag_name = TAGS.get(tag, tag)
        if tag_name == 'Orientation':
            if value == 3:
                retValue = 180
            elif value == 6:
                retValue = 270
            elif value == 8:
                retValue = 90
            else: # value == 1:
                retValue = 0
            break
    
    return retValue

# EXIF 데이터에서 GPS 정보를 파싱하여 딕셔너리 형태로 반환
def _parseGPSInfo(exif_data):
    gps_info = {}
    if 'GPSInfo' in exif_data:
        for key in exif_data['GPSInfo'].keys():
            decode = GPSTAGS.get(key, key)
            gps_info[decode] = exif_data['GPSInfo'][key]

    return gps_info

# 도, 분, 초 형식의 GPS 데이터를 도 형식으로 변환
def _convertToDegrees(value):
    
    d = 0.0
    if 0 < value[0]:
        d = float(value[0])
    
    m = 0.0
    if 0 < value[1]:
        m = float(value[1]) / 60.0
        
    s = 0.0
    if 0 < value[2]:
        s = float(value[2]) / 3600.0
        
    return d + m + s

# GPS 정보를 사용하여 위도와 경도를 도 형식으로 반환
def _getlatlon(gps_info):
    lat,lon = 0.0, 0.0
    if 'GPSLatitude' in gps_info and 'GPSLatitudeRef' in gps_info:
        lat = _convertToDegrees(gps_info['GPSLatitude'])
        if gps_info['GPSLatitudeRef'] != 'N':
            lat = -lat

    if 'GPSLongitude' in gps_info and 'GPSLongitudeRef' in gps_info:
        lon = _convertToDegrees(gps_info['GPSLongitude'])
        if gps_info['GPSLongitudeRef'] != 'E':
            lon = -lon

    return lat, lon

