#!/usr/bin/env python3
"""
cromakga3d - Android Build

항상 clean 빌드다. 증분 빌드는 crBuildInfo.h 를 다시 컴파일하지 않아 buildstamp 가 거짓말을
하게 되고, 산출물을 신뢰할 수 없어진다.

설치와 logcat 은 __adbtool.py 가 갖고 있다 — 기기 선택과 에러 안내가 한 벌만 존재하도록.
"""

import os
import re
import sys
import subprocess

import __adbtool as adbtool
from __adbtool import col, CYAN, GREEN, RED, YELLOW, GRAY, WHITE

# ── Paths ────────────────────────────────────────────────────────
PROJECT_DIR  = os.path.dirname(os.path.abspath(__file__))
ANDROID_DIR  = os.path.join(PROJECT_DIR, "android")
GRADLEW      = os.path.join(ANDROID_DIR, "gradlew.bat")
BUILD_GRADLE = os.path.join(ANDROID_DIR, "app", "build.gradle")

# ── Print helpers ─────────────────────────────────────────────────
print_section = adbtool.print_section
print_step    = adbtool.print_step
print_ok      = adbtool.print_ok
print_warn    = adbtool.print_warn
print_hint    = adbtool.print_hint
print_fail    = adbtool.print_fail
fmt_size      = adbtool.fmt_size
read_key      = adbtool.read_key

def print_header(package):
    os.system("cls")
    print()
    print(col(CYAN, "  +==========================================+"))
    print(col(CYAN, "  |    cromakga3d  .  Android Build          |"))
    print(col(CYAN, "  +==========================================+"))
    print()
    print(col(GRAY, "  Project  :  " + PROJECT_DIR))
    print(col(GRAY, "  Package  :  " + package))
    print(col(GRAY, "  Output   :  " + os.path.relpath(adbtool.OUTPUT_DIR, PROJECT_DIR)))

def select_build_type():
    print()
    print(col(CYAN, "  Select build type:"))
    print(col(GRAY, "  -----------------------------------------"))
    print(col(WHITE, "    R      ->  Release   (apk + aab, 서명 필요)"))
    print(col(WHITE, "    D      ->  Debug     (apk)"))
    print(col(WHITE, "    SPACE  ->  Skip build (__adbtool.py 로 바로)"))
    print(col(GRAY,  "    other  ->  exit"))
    print()

    key = read_key()
    if key == "r":
        print(col(GREEN, "  Release"))
        return "Release"
    if key == "d":
        print(col(YELLOW, "  Debug"))
        return "Debug"
    if key == " ":
        print(col(YELLOW, "  Skip build"))
        return None

    print(col(YELLOW, "  cancelled."))
    print()
    sys.exit(0)

# ── Pre-flight ────────────────────────────────────────────────────
def check_keystore():
    """서명 자료가 실제로 있는지 빌드 전에 본다. 없으면 몇 분 굽고 나서 서명 단계에서 죽는다.
    비밀번호는 읽지 않는다 — 키 이름과 파일 존재만 확인한다. 이 저장소는 공개다."""
    with open(BUILD_GRADLE, "r", encoding="utf-8") as f:
        match = re.search(r'def\s+signingFile\s*=\s*file\("([^"]+)"\)', f.read())

    if match is None:
        print_fail("signingFile 경로를 찾을 수 없습니다: " + BUILD_GRADLE)

    properties_path = match.group(1)
    if not os.path.isfile(properties_path):
        print_fail("서명 설정 파일이 없습니다: " + properties_path + "\n"
                   "    -> 키스토어를 만들고 이 경로에 properties 를 두세요")

    store = ""
    with open(properties_path, "r", encoding="utf-8") as f:
        for line in f:
            key, sep, value = line.partition("=")
            if sep and key.strip() == "CROMAKGA_STORE_FILE":
                store = value.strip()

    if not store:
        print_fail("CROMAKGA_STORE_FILE 항목이 없습니다: " + properties_path)
    if not os.path.isfile(store):
        print_fail("키스토어 파일이 없습니다: " + store + "\n"
                   "    -> properties 의 CROMAKGA_STORE_FILE 경로를 확인하세요")

    print_ok("키스토어: " + os.path.basename(store))

def preflight(build_type):
    print_step("[1/3] 사전 확인")

    if not os.path.isfile(GRADLEW):
        print_fail("gradlew.bat 이 없습니다: " + GRADLEW)

    if build_type == "Release":
        check_keystore()
    else:
        print_ok("Debug — 서명 확인 생략")

    adbtool.require_adb()
    adbtool.report_devices(adbtool.list_devices())

# ── Build ─────────────────────────────────────────────────────────
def gradle(tasks):
    return subprocess.run([GRADLEW] + tasks, cwd=ANDROID_DIR).returncode

def build(build_type):
    print_step("[2/3] clean")
    # clean 을 빌드 태스크와 같은 호출에 섞지 않는다 — Gradle 이 up-to-date 판정을 그르친다
    if gradle(["clean"]) != 0:
        print_fail("clean 실패")
    print_ok("clean 완료")

    tasks = ["assembleRelease", "bundleRelease"] if build_type == "Release" else ["assembleDebug"]

    print_step("[3/3] " + " ".join(tasks))
    if gradle(tasks) != 0:
        print_fail("빌드 실패")

    print()
    print(col(GREEN, "  +==========================================+"))
    print(col(GREEN, "  |  v  Build succeeded!                    |"))
    print(col(GREEN, "  +==========================================+"))

def report_artifacts(build_type):
    if build_type == "Release":
        paths = [adbtool.APK["Release"], adbtool.AAB]
    else:
        paths = [adbtool.APK["Debug"]]

    print()
    print(col(GRAY, "  -----------------------------------------"))
    for path in paths:
        name = os.path.basename(path)
        if os.path.isfile(path):
            print(col(GREEN, "  v  " + name.ljust(20) + fmt_size(os.path.getsize(path)).rjust(10)))
            print(col(GRAY,  "     " + os.path.relpath(path, PROJECT_DIR)))
        else:
            print(col(RED,   "  x  " + name.ljust(20) + "  (not found)"))
    print(col(GRAY, "  -----------------------------------------"))

    if build_type == "Release":
        # .aab 는 adb 로 설치할 수 없다. Play 콘솔에 웹으로 올리는 물건이라 여기서 끝이다.
        print(col(GRAY, "  .aab 는 Play 콘솔 업로드용 — 설치는 .apk 로 합니다"))

# ── Main ──────────────────────────────────────────────────────────
def main():
    package = adbtool.read_application_id()

    print_header(package)
    build_type = select_build_type()

    if build_type is not None:
        print_section("BUILD  [" + build_type + "]")
        preflight(build_type)
        build(build_type)
        report_artifacts(build_type)

    print_section("ADB TOOL")
    adbtool.menu_loop(package)

if __name__ == "__main__":
    main()
