from dataclasses import dataclass
from collections.abc import Generator
from contextlib import contextmanager

import manim as mm

from euclid_geometry.point import Point


@dataclass
class Construction:
    playable: mm.Animation
    result: mm.VMobject


@dataclass
class DotConstruction (Construction):
    g_point: Point

@dataclass
class LabelConstruction(Construction):
    g_point: Point
    label:str


@dataclass
class LineConstruction(Construction):
    pa: DotConstruction
    pb: DotConstruction


#: Default style for some elements
style = {
    "scene": {
        "background_color": "#CCCCCC"
    },
    #: Style for points
    "dot": {
        "fill_color": mm.WHITE,
        "stroke_color": mm.BLACK,
        "stroke_width": 1,
        "radius": 0.025
    },
    #: Style for construction line (most lines are construction line)
    "cline": {
        "fill_color": mm.TEAL_C,
        "stroke_color": mm.TEAL_C,
        "stroke_width": 2,
        "me": {
            "add": 0.2
        }
    },
    #: label
    "label": {
        "color": mm.BLACK,
        "font_size": 24
    },
    #: style for axis
    "axis": {
        "stroke_width": 1,
        #"stroke_color": BLACK,
        "font_size": 24,
        "decimal_number_config": {"color": mm.BLACK},
        "include_ticks": True
    }
}


@contextmanager
def styling(temp: dict[str:any])-> Generator[None,None,None]:
    """ temporary modifies the global ``style`` object using a context manager.

    Inside the ``with`` statement, the modified config will be used.  After
    context manager exits, the config will be restored to its original state.
    Example::

        my_style = {
            "dot": {
                "fill_color": RED
            }
        }
        with styling(my_style):
            scene = MyScene()
            scene.render()


    :return:
    """
    global style
    original = style.copy()
    temp = {k: v for k, v in temp.items() if k in original}
    style.update(temp)
    try:
        yield
    finally:
        style.update(original)
