# -*- coding: utf-8 -*-
"""Package the whole project (code + data + results + report) into one zip.

Excludes environment/tool artifacts (.venv, tools/, third_party/) and
intermediate logs/dense-intermediates that can be regenerated.
"""
import os, zipfile

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
OUT = os.path.join(ROOT, "cidaren_project.zip")

# top-level items to include (relative to ROOT)
INCLUDE = ["report.md", "scripts", "nerf", "output", "mvs_project"]

# relative path fragments to EXCLUDE
EXCLUDE_SUBSTR = [
    "output/colmap/dense",          # failed patch-match dense + undistorted images
    "output/colmap/db.db",          # feature database (regenerable)
    "output/mvs_smoke",             # smoke test
    "output/mvs_run.log",
    "output/nerf_train.log",
    "output/colmap/feature.log",
    "output/colmap/match.log",
    "output/colmap/mapper.log",
    "output/colmap/undistort.log",
    "output/colmap/patch_match.log",
    "output/colmap/patch_match2.log",
    "output/colmap/patch_match3.log",
    "output/colmap/patch_match4.log",
    "output/colmap/fusion.log",
    "tools",                        # COLMAP binary + torch wheel (regenerable)
    "third_party",
    "scripts/dgr.tar.gz",
    "scripts/diff-gaussian-rasterization-master",
]


def rel(p):
    return os.path.relpath(p, ROOT).replace("\\", "/")


def excluded(rp):
    for sub in EXCLUDE_SUBSTR:
        if sub in rp:
            return True
    return False


def main():
    files = []
    for inc in INCLUDE:
        full = os.path.join(ROOT, inc)
        if os.path.isfile(full):
            files.append(full)
        elif os.path.isdir(full):
            for dp, dn, fn in os.walk(full):
                for name in fn:
                    files.append(os.path.join(dp, name))
        else:
            print("skip missing:", inc)

    files = sorted(set(files))
    files = [f for f in files if not excluded(rel(f))]

    total = sum(os.path.getsize(f) for f in files)
    print(f"packing {len(files)} files, {total/1e6:.1f} MB -> {rel(OUT)}")

    done = 0
    with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED, compresslevel=6) as z:
        for f in files:
            arc = rel(f)
            z.write(f, arc)
            done += os.path.getsize(f)
            if done % (200 << 20) < (64 << 20):
                print(f"  {done/1e6:.0f}/{total/1e6:.0f} MB")

    sz = os.path.getsize(OUT)
    print(f"done: {rel(OUT)} = {sz/1e6:.1f} MB")


if __name__ == "__main__":
    main()
