"""Derivative of example8 that can package the generated 2D geometry as a .ycpkg."""

from __future__ import annotations

import argparse
import random
import shutil
from pathlib import Path

from yapcad.ezdxf_drawable import ezdxfDraw
from yapcad.geom import arc, bbox, mirror, point, add, cos, sin, pi2, iscircle
from yapcad.poly import Polygon
from yapcad.package import create_package_from_entities

from examples import example10  # reuse randomPoints helper


def draw_legend(drawer: ezdxfDraw) -> None:
    drawer.layer = 'DOCUMENTATION'
    att = {'style': 'OpenSans-Bold', 'height': 2.5}
    drawer.draw_text("yapCAD", point(5, 15), attr=att)
    drawer.draw_text("example8_package.py", point(5, 11), attr=att)
    drawer.draw_text("Polygon flowers, mirrored geometry", point(5, 7), attr=att)
    drawer.layer = False


def flower(center=point(0, 0),
           petals=10,
           min_diam=5.0,
           max_diam=15,
           min_radius=20,
           max_radius=40,
           inside_radius=5,
           return_poly=False):

    glist = []
    for i in range(petals):
        angle = i * 360 / petals
        anrad = angle * pi2 / 360.0

        an2 = (((i + 0.5) / petals) % 1.0) * 360
        an2rad = an2 * pi2 / 360.0

        radius = (max_radius - min_radius) * random.random() + min_radius
        diam = (max_diam - min_diam) * random.random() + min_diam
        pnt = add(point(cos(anrad) * radius, sin(anrad) * radius), center)
        pnt2 = add(point(cos(an2rad) * inside_radius, sin(an2rad) * inside_radius), center)
        a = arc(pnt, diam / 2)
        glist.append(a)
        glist.append(pnt2)

    poly = Polygon(glist)
    if return_poly:
        return poly
    return poly.geom


def mirror_array(pnt=point(-45, 45)):
    flwr = flower(pnt, return_poly=True)
    glist = flwr.geom
    bb = bbox(glist)
    flwr2 = Polygon(flwr.geom)
    flwr2.grow(1.0)
    glist.extend(flwr2.geom)

    random_points = example10.randomPoints(bb, 500)
    for p in random_points:
        if flwr.isinsideXY(p):
            glist.append(arc(p, 0.4))

    ply = [
        point(bb[0]),
        point(bb[1][0], bb[0][1]),
        point(bb[1]),
        point(bb[0][0], bb[1][1]),
    ]
    glist = glist + ply
    glist = glist + mirror(glist, 'yz')
    glist = glist + mirror(glist, 'xz')
    return glist


def build_arg_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="Generate example8 geometry and optional package.")
    parser.add_argument("--output", default="example8-out", help="Base filename for DXF output.")
    parser.add_argument("--package", type=Path, help="Optional directory for .ycpkg output.")
    parser.add_argument("--name", default="Example 8 Flowers", help="Package manifest name.")
    parser.add_argument("--version", default="0.1.0", help="Package manifest version.")
    parser.add_argument(
        "--description",
        default="2D flower sketch generated by example8",
        help="Package manifest description.",
    )
    parser.add_argument(
        "--overwrite",
        action="store_true",
        help="Overwrite existing package directory if present.",
    )
    parser.add_argument("--no-display", action="store_true", help="Disable DXF viewer pop-up.")
    return parser


def main(argv: list[str] | None = None) -> None:
    parser = build_arg_parser()
    args = parser.parse_args(argv)

    glist = mirror_array()

    print("example8_package.py -- yapCAD computational geometry and DXF drawing example")
    drawer = ezdxfDraw()
    drawer.filename = args.output
    draw_legend(drawer)

    circles = []
    others = []
    for g in glist:
        if iscircle(g):
            circles.append(g)
        else:
            others.append(g)
    drawer.linecolor = 'white'
    drawer.draw(others)
    drawer.linecolor = 'aqua'
    drawer.draw(circles)

    drawer.display()  # persists the DXF to disk
    dxf_path = Path(f"{args.output}.dxf").resolve()
    print(f"DXF written to {dxf_path}")

    if args.package:
        manifest = create_package_from_entities(
            [{'geometry': glist, 'metadata': {'layer': 'flowers'}}],
            args.package,
            name=args.name,
            version=args.version,
            description=args.description,
            units="mm",
            overwrite=args.overwrite,
        )
        export_target = manifest.root / "exports" / dxf_path.name
        export_target.parent.mkdir(parents=True, exist_ok=True)
        shutil.copyfile(dxf_path, export_target)
        manifest.data.setdefault("exports", []).append({
            "id": "dxf-main",
            "kind": "dxf",
            "path": str(export_target.relative_to(manifest.root)),
        })
        tags = manifest.data.setdefault("tags", [])
        if "2d" not in tags:
            tags.append("2d")
        if "flowers" not in tags:
            tags.append("flowers")
        manifest.recompute_hashes()
        manifest.save()
        print(f"Package created at {manifest.manifest_path}")

    # Legacy flag retained for parity; ezdxfDraw.display() simply writes the file
    # so there is no additional GUI to launch here.


if __name__ == "__main__":
    main()
