import json

import FreeCAD as App
import Part
import Sketcher

from freecad_mutation_evidence import capture_property_mutation


COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"


def add_rectangle(sketch, xmin, ymin, xmax, ymax):
    points = [(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]
    for index, start in enumerate(points):
        end = points[(index + 1) % len(points)]
        sketch.addGeometry(Part.LineSegment(App.Vector(start[0], start[1], 0), App.Vector(end[0], end[1], 0)), False)


def status(feature):
    try:
        status_string = str(feature.getStatusString())
    except Exception:
        status_string = ""
    shape = feature.Shape
    return {
        "typeId": feature.TypeId,
        "passed": not shape.isNull() and shape.isValid() and len(shape.Solids) == 1,
        "status": status_string,
        "shapeNull": bool(shape.isNull()),
        "shapeValid": bool(shape.isValid()) if not shape.isNull() else False,
        "solids": len(shape.Solids) if not shape.isNull() else 0,
        "faces": len(shape.Faces) if not shape.isNull() else 0,
        "volume": float(shape.Volume) if not shape.isNull() else 0.0,
    }


def run_revolution():
    document = App.newDocument("PartDesignRevolutionOracle")
    try:
        body = document.addObject("PartDesign::Body", "Body")
        sketch = document.addObject("Sketcher::SketchObject", "Profile")
        body.addObject(sketch)
        add_rectangle(sketch, -1, 2, 1, 4)
        document.recompute()
        feature = document.addObject("PartDesign::Revolution", "Revolution")
        body.addObject(feature)
        feature.Profile = sketch
        feature.ReferenceAxis = (sketch, ["H_Axis"])
        feature.Angle = 360
        document.recompute()
        mutation = capture_property_mutation(document, feature, "Angle", 270.0)
        return {"id": "partdesign-revolution", "operation": "revolution", "mutation": mutation, **status(feature)}
    except Exception as error:
        return {"id": "partdesign-revolution", "operation": "revolution", "passed": False, "error": str(error)}
    finally:
        App.closeDocument(document.Name)


def run_groove():
    document = App.newDocument("PartDesignGrooveOracle")
    try:
        body = document.addObject("PartDesign::Body", "Body")
        base = document.addObject("PartDesign::AdditiveBox", "Base")
        body.addObject(base)
        base.Length = 10
        base.Width = 10
        base.Height = 10
        document.recompute()
        sketch = document.addObject("Sketcher::SketchObject", "Profile")
        body.addObject(sketch)
        add_rectangle(sketch, 2, 1, 4, 2)
        document.recompute()
        feature = document.addObject("PartDesign::Groove", "Groove")
        body.addObject(feature)
        feature.Profile = sketch
        feature.ReferenceAxis = (sketch, ["H_Axis"])
        feature.Angle = 180
        document.recompute()
        mutation = capture_property_mutation(document, feature, "Angle", 120.0)
        return {"id": "partdesign-groove", "operation": "groove", "mutation": mutation, **status(feature)}
    except Exception as error:
        return {"id": "partdesign-groove", "operation": "groove", "passed": False, "error": str(error)}
    finally:
        App.closeDocument(document.Name)


cases = [run_revolution(), run_groove()]
report = {
    "schemaVersion": 1,
    "baselineId": "freecad-1.1.1-partdesign-revolution-groove-oracle",
    "freecadVersion": ".".join(App.Version()[0:3]),
    "gitCommit": COMMIT,
    "status": "pass" if all(case.get("passed") for case in cases) else "failed",
    "summary": {"cases": len(cases), "passed": sum(1 for case in cases if case.get("passed"))},
    "cases": cases,
}
print("FREECAD_PARTDESIGN_REVOLUTION_GROOVE_ORACLE_RESULT=" + json.dumps(report, sort_keys=True))
