from yta_editor_time.temporal_specification.temporal_resolution import TemporalResolution
from yta_editor_time.enum import TimeSpace, TimeAnchor
from dataclasses import dataclass
from typing import Union


@dataclass(frozen = True)
class TimeRangeSpecification:
    """
    A time range specification in which an element
    should be applied.
    """

    def __init__(
        self,
        space: TimeSpace,
        anchor: TimeAnchor,
        start: Union[int, float, None],
        end: Union[int, float, None],
        duration: Union[float, None]
    ):
        space = TimeSpace.to_enum(space)
        anchor = TimeAnchor.to_enum(anchor)

        self.space: TimeSpace = space
        """
        The time space in which we are specificating the
        time range to be applied.
        """
        self.anchor: TimeAnchor = anchor
        """
        The position, element or part of it to which this
        specification is anchored.
        """
        self.start: Union[int, float, None] = start
        """
        The start time moment of this time specification.
        """
        self.end: Union[int, float, None] = end
        """
        The end time moment of this time specification.
        """
        self.duration: Union[float, None] = duration
        """
        The total duration of this time specification.
        """

    def is_active(
        self,
        evaluation_context: 'VideoEditorEvaluationContext'
    ) -> bool:
        """
        Check if the element with this `TimeRangeSpecification`
        is active or not according to the `evaluation_context`
        provided.
        """
        return self.space.to_effective_time_range(
            start = self.start,
            end = self.end
        ).is_active(evaluation_context)
    
    def resolve(
        self,
        evaluation_context: 'VideoEditorEvaluationContext'
    ):
        """
        Get the `start` and `end` time moments of this time
        range specification by resolving it according to the
        `evaluation_context` provided.
        """
        if not self.is_active(evaluation_context):
            return TemporalResolution(
                is_active = False,
                t_local_normalized = None,
                weight = 1.0
            )

        # TODO: Resolving according to the type
        if self.anchor == TimeSpace.LOCAL_TIME_NORMALIZED:
            if self.anchor == TimeAnchor.START:
                start = (
                    self.start or
                    0.0
                )
                end = (
                    self.end or
                    start + self.duration
                )
            elif self.anchor == TimeAnchor.END:
                end = 1.0 - (
                        self.start or
                        0.0
                    )
                start = end - self.duration
        elif self.anchor == TimeSpace.LOCAL_TIME:
            if self.anchor == TimeAnchor.START:
                start = (
                    self.start or
                    0.0
                )
                end = (
                    self.end or
                    start + self.duration
                )
            elif self.anchor == TimeAnchor.END:
                end = evaluation_context.item_duration - (
                        self.start or
                        0.0
                    )
                start = end - self.duration
        elif self.anchor == TimeSpace.LOCAL_FRAME_INDEXES:
            if self.anchor == TimeAnchor.START:
                start = (
                    self.start or
                    0
                )
                end = (
                    self.end or
                    # TODO: Is this value the duration in frames or
                    # the total amount of frames (?)
                    start + self.duration_frames
                )
            elif self.anchor == TimeAnchor.END:
                end = evaluation_context.number_of_frames - 1 - (
                        self.start or
                        0
                    )
                start = end - self.duration_frames
        else:
            raise Exception('Something went wrong...')
        # elif self.anchor == TimeSpace.GLOBAL:
        #     if self.anchor == TimeAnchor.START:
        #         start = (
        #             self.start or
        #             0.0
        #         )
        #         end = (
        #             self.end or
        #             start + self.duration
        #         )
        #     elif self.anchor == TimeAnchor.END:
        #         end = evaluation_context.item_duration - (
        #                 self.start or
        #                 0.0
        #             )
        #         start = end - self.duration 

        return TemporalResolution(
            is_active = True,
            t_local_normalized = evaluation_context.t_normalized,
            weight = 1.0
        ) 


        t = evaluation_context.t_normalized

        # TODO: I think this conditions vary depending on the
        # TimeSpace and TimeAnchor
        if (
            t < self.start or
            t > self.end
        ):
            return TemporalResolution(
                is_active = False,
                t_local_normalized = None,
                weight = 1.0
            )

        # TODO: This calculation is used again and again...
        t_local_normalized = (t - self.start) / (self.end - self.start)

        return TemporalResolution(
            is_active = True,
            t_local_normalized = t_local_normalized,
            weight = 1.0
        )


"""
# Todo el clip
TimeRangeSpec(
    space=ITEM_NORMALIZED,
    anchor=START,
    start=0.0,
    end=1.0
)

# Últimos 0.5s
TimeRangeSpec(
    space=ITEM_SECONDS,
    anchor=END,
    duration=0.5
)
"""

"""
| Dominio temporal               | `domain.min` | `domain.max`           |
| ------------------------------ | ------------ | ---------------------- |
| `t_normalized` (local clip)    | `0.0`        | `1.0`                  |
| `t_global_normalized`          | `0.0`        | `1.0`                  |
| `t` (tiempo local en segundos) | `0.0`        | `clip_duration`        |
| `t_global` (timeline)          | `0.0`        | `timeline_duration`    |
| `frame_index`                  | `0`          | `number_of_frames - 1` |

"""