# -*- coding: utf-8 -*-
"""
HWP/HWPX ↔ HTML/CSS 변환 유틸리티

hwpx_domain_guide.md의 매핑 테이블을 코드화.
하드코딩 없이 이 모듈의 함수/상수를 참조하여 정확한 변환을 수행한다.

참조: 한글과컴퓨터 "글 문서 파일 구조 5.0" (revision 1.3, 2018-11-08)
"""


# ================================================================
#  §1. 단위 변환
# ================================================================

def hwpunit_to_mm(hwpunit):
    """HWPUNIT → mm  (1 HWPUNIT = 1/7200 inch)"""
    return hwpunit / 7200 * 25.4

def hwpunit_to_pt(hwpunit):
    """HWPUNIT → pt"""
    return hwpunit / 7200 * 72

def hwpunit_to_px(hwpunit, dpi=96):
    """HWPUNIT → px (기본 96dpi)"""
    return hwpunit / 7200 * dpi

def mm_to_hwpunit(mm):
    """mm → HWPUNIT"""
    return mm / 25.4 * 7200

def pt_to_hwpunit(pt):
    """pt → HWPUNIT"""
    return pt / 72 * 7200

def px_to_hwpunit(px, dpi=96):
    """px → HWPUNIT"""
    return px / dpi * 7200

def charsize_to_pt(hwp_size):
    """HWP 글자 크기 → pt (100 스케일 제거)
    예: 1000 → 10pt, 2400 → 24pt
    """
    return hwp_size / 100

def pt_to_charsize(pt):
    """pt → HWP 글자 크기
    예: 10pt → 1000, 24pt → 2400
    """
    return int(pt * 100)


# ================================================================
#  §1.3 색상 변환
# ================================================================

def colorref_to_css(colorref):
    """HWP COLORREF (0x00BBGGRR) → CSS #RRGGBB
    
    HWP는 리틀 엔디안 BGR 순서:
    - 0x00FF0000 → B=255,G=0,R=0 → #0000ff (파랑)
    - 0x000000FF → B=0,G=0,R=255 → #ff0000 (빨강)
    """
    r = colorref & 0xFF
    g = (colorref >> 8) & 0xFF
    b = (colorref >> 16) & 0xFF
    return f'#{r:02x}{g:02x}{b:02x}'

def css_to_colorref(css_color):
    """CSS #RRGGBB → HWP COLORREF (0x00BBGGRR)"""
    css_color = css_color.lstrip('#')
    if len(css_color) == 3:  # 단축형 #rgb → #rrggbb
        css_color = ''.join(c * 2 for c in css_color)
    r = int(css_color[0:2], 16)
    g = int(css_color[2:4], 16)
    b = int(css_color[4:6], 16)
    return (b << 16) | (g << 8) | r


# ================================================================
#  §2. 테두리/배경 (BorderFill) 매핑
# ================================================================

# §2.1 테두리선 종류: HWPX type → CSS border-style
BORDER_TYPE_TO_CSS = {
    'NONE':           'none',
    'SOLID':          'solid',
    'DASH':           'dashed',
    'DOT':            'dotted',
    'DASH_DOT':       'dashed',     # CSS 근사
    'DASH_DOT_DOT':   'dashed',     # CSS 근사
    'LONG_DASH':      'dashed',
    'CIRCLE':         'dotted',     # CSS 근사 (큰 동그라미 → dot)
    'DOUBLE':         'double',
    'THIN_THICK':     'double',     # CSS 근사
    'THICK_THIN':     'double',     # CSS 근사
    'THIN_THICK_THIN':'double',     # CSS 근사
    'WAVE':           'solid',      # CSS 근사 (물결 → 실선)
    'DOUBLE_WAVE':    'double',     # CSS 근사
    'THICK_3D':       'ridge',
    'THICK_3D_REV':   'groove',
    '3D':             'outset',
    '3D_REV':         'inset',
}

# CSS border-style → HWPX type (역방향)
CSS_TO_BORDER_TYPE = {
    'none':   'NONE',
    'solid':  'SOLID',
    'dashed': 'DASH',
    'dotted': 'DOT',
    'double': 'DOUBLE',
    'ridge':  'THICK_3D',
    'groove': 'THICK_3D_REV',
    'outset': '3D',
    'inset':  '3D_REV',
}

# §2.2 HWP 바이너리 테두리 굵기 값 → 실제 mm
BORDER_WIDTH_HWP_TO_MM = {
    0: 0.1,  1: 0.12, 2: 0.15, 3: 0.2,  4: 0.25, 5: 0.3,
    6: 0.4,  7: 0.5,  8: 0.6,  9: 0.7, 10: 1.0, 11: 1.5,
    12: 2.0, 13: 3.0, 14: 4.0, 15: 5.0,
}


# ================================================================
#  §5. 정렬 매핑
# ================================================================

# §5.1 HWPX align → CSS text-align
ALIGN_TO_CSS = {
    'JUSTIFY':          'justify',
    'LEFT':             'left',
    'RIGHT':            'right',
    'CENTER':           'center',
    'DISTRIBUTE':       'justify',  # CSS 근사
    'DISTRIBUTE_SPACE': 'justify',  # CSS 근사
}

# CSS text-align → HWPX align (역방향)
CSS_TO_ALIGN = {
    'justify': 'JUSTIFY',
    'left':    'LEFT',
    'right':   'RIGHT',
    'center':  'CENTER',
}


# ================================================================
#  §5.2 줄 간격 매핑
# ================================================================

LINE_SPACING_TYPE_TO_CSS = {
    'PERCENT':        'percent',    # 글자에 따라 (%) → line-height: 160%
    'FIXED':          'fixed',      # 고정값 → line-height: 24pt
    'BETWEEN_LINES':  'between',    # 여백만 지정
    'AT_LEAST':       'at_least',   # 최소
}


# ================================================================
#  종합 변환 함수
# ================================================================

def hwpx_border_to_css(border_attrs):
    """HWPX 테두리 속성 dict → CSS border 문자열
    
    Args:
        border_attrs: {'type': 'SOLID', 'width': '0.12mm', 'color': '#000000'}
        
    Returns:
        '0.12mm solid #000000' 또는 'none'
    """
    btype = border_attrs.get('type', 'NONE')
    if btype == 'NONE' or btype is None:
        return 'none'
    
    width = border_attrs.get('width', '0.12mm')
    color = border_attrs.get('color', '#000000')
    css_style = BORDER_TYPE_TO_CSS.get(btype, 'solid')
    
    return f'{width} {css_style} {color}'


def css_border_to_hwpx(css_border):
    """CSS border 문자열 → HWPX 속성 dict
    
    Args:
        css_border: '0.12mm solid #000000' 또는 'none'
        
    Returns:
        {'type': 'SOLID', 'width': '0.12mm', 'color': '#000000'}
    """
    if not css_border or css_border.strip() == 'none':
        return {'type': 'NONE', 'width': '0mm', 'color': '#000000'}
    
    parts = css_border.strip().split()
    width = parts[0] if len(parts) > 0 else '0.12mm'
    style = parts[1] if len(parts) > 1 else 'solid'
    color = parts[2] if len(parts) > 2 else '#000000'
    
    return {
        'type': CSS_TO_BORDER_TYPE.get(style, 'SOLID'),
        'width': width,
        'color': color,
    }


def hwpx_borderfill_to_css(bf_element_attrs):
    """HWPX <hh:borderFill> 전체 속성 → CSS dict
    
    Args:
        bf_element_attrs: {
            'left':   {'type': 'SOLID', 'width': '0.12mm', 'color': '#000000'},
            'right':  {'type': 'SOLID', 'width': '0.12mm', 'color': '#000000'},
            'top':    {'type': 'SOLID', 'width': '0.12mm', 'color': '#000000'},
            'bottom': {'type': 'SOLID', 'width': '0.12mm', 'color': '#000000'},
            'background': '#E8F5E9' or None,
        }
        
    Returns:
        {
            'border-left': '0.12mm solid #000000',
            'border-right': '0.12mm solid #000000',
            'border-top': '0.12mm solid #000000',
            'border-bottom': '0.12mm solid #000000',
            'background-color': '#E8F5E9',
        }
    """
    css = {}
    
    for side in ['left', 'right', 'top', 'bottom']:
        border = bf_element_attrs.get(side, {})
        css[f'border-{side}'] = hwpx_border_to_css(border)
    
    bg = bf_element_attrs.get('background')
    if bg and bg != 'none':
        css['background-color'] = bg
    
    return css


def hwpx_align_to_css(hwpx_align):
    """HWPX 정렬 값 → CSS text-align"""
    return ALIGN_TO_CSS.get(hwpx_align, 'left')


def css_align_to_hwpx(css_align):
    """CSS text-align → HWPX 정렬 값"""
    return CSS_TO_ALIGN.get(css_align, 'LEFT')


def hwpx_line_spacing_to_css(spacing_type, spacing_value):
    """HWPX 줄 간격 → CSS line-height
    
    Args:
        spacing_type: 'PERCENT' | 'FIXED' | 'BETWEEN_LINES' | 'AT_LEAST'
        spacing_value: 숫자값
        
    Returns:
        CSS line-height 문자열 (예: '160%', '24pt')
    """
    if spacing_type == 'PERCENT':
        return f'{spacing_value}%'
    elif spacing_type == 'FIXED':
        pt = hwpunit_to_pt(spacing_value)
        return f'{pt:.1f}pt'
    else:
        return f'{spacing_value}%'  # 기본 근사


# ================================================================
#  용지 크기 사전 정의 (§7.1)
# ================================================================

PAPER_SIZES = {
    'A4':     {'width_mm': 210,   'height_mm': 297,   'width_hu': 59528,  'height_hu': 84188},
    'A3':     {'width_mm': 297,   'height_mm': 420,   'width_hu': 84188,  'height_hu': 119055},
    'B5':     {'width_mm': 176,   'height_mm': 250,   'width_hu': 49896,  'height_hu': 70866},
    'Letter': {'width_mm': 215.9, 'height_mm': 279.4, 'width_hu': 61200,  'height_hu': 79200},
    'Legal':  {'width_mm': 215.9, 'height_mm': 355.6, 'width_hu': 61200,  'height_hu': 100800},
}

def detect_paper_size(width_hu, height_hu, tolerance=200):
    """HWPUNIT 용지 크기 → 용지 이름 추정
    
    Args:
        width_hu: 가로 크기 (HWPUNIT)
        height_hu: 세로 크기 (HWPUNIT)
        tolerance: 허용 오차 (HWPUNIT)
        
    Returns:
        'A4', 'A3', 'Letter' 등 또는 'custom'
    """
    for name, size in PAPER_SIZES.items():
        if (abs(width_hu - size['width_hu']) <= tolerance and 
            abs(height_hu - size['height_hu']) <= tolerance):
            return name
        # landscape 체크
        if (abs(width_hu - size['height_hu']) <= tolerance and 
            abs(height_hu - size['width_hu']) <= tolerance):
            return f'{name}_landscape'
    return 'custom'


# ================================================================
#  편의 함수
# ================================================================

def css_style_string(css_dict):
    """CSS dict → CSS style 문자열
    
    예: {'border-left': '1px solid #000', 'padding': '5mm'}
    → 'border-left: 1px solid #000; padding: 5mm;'
    """
    return ' '.join(f'{k}: {v};' for k, v in css_dict.items() if v)


def mm_format(hwpunit, decimal=1):
    """HWPUNIT → 'Xmm' 포맷 문자열"""
    mm = hwpunit_to_mm(hwpunit)
    return f'{mm:.{decimal}f}mm'