from .base import BaseCZMLObject
from .common import Deletable, HasAlignment, Interpolatable
from .enums import ClockRanges, ClockSteps, LabelStyles
from .types import Cartesian3Value, Uri


# noinspection PyPep8Naming
class Position(BaseCZMLObject, Interpolatable, Deletable):
    """Defines a position. The position can optionally vary over time."""

    KNOWN_PROPERTIES = [
        "delete",
        "epoch",
        "interpolationAlgorithm",
        "interpolationDegree",
        "referenceFrame",
        "cartesian",
    ]

    def __init__(
        self,
        *,
        delete=None,
        epoch=None,
        interpolationAlgorithm=None,
        interpolationDegree=None,
        referenceFrame=None,
        cartesian=None,
    ):
        if isinstance(cartesian, list):
            cartesian = Cartesian3Value(values=cartesian)

        self._delete = delete
        self._epoch = epoch
        self._interpolation_algorithm = interpolationAlgorithm
        self._interpolation_degree = interpolationDegree
        self._reference_frame = referenceFrame
        self._cartesian = cartesian

    @property
    def referenceFrame(self):
        """The reference frame in which cartesian positions are specified."""
        return self._reference_frame

    @property
    def cartesian(self):
        """The position specified as a three-dimensional Cartesian value.

        The value [X, Y, Z] is specified
        in meters relative to the ReferenceFrame.
        """
        return self._cartesian


# noinspection PyPep8Naming
class Billboard(BaseCZMLObject, HasAlignment):
    """A billboard, or viewport-aligned image.

    The billboard is positioned in the scene by the position property.
    A billboard is sometimes called a marker.
    """

    KNOWN_PROPERTIES = [
        "show",
        "image",
        "scale",
        "pixelOffset",
        "eyeOffset",
        "horizontalOrigin",
        "verticalOrigin",
        "heightReference",
        "color",
        "rotation",
        "alignedAxis",
        "sizeInMeters",
        "width",
        "height",
        "scaleByDistance",
        "translucencyByDistance",
        "pixelOffsetScaleByDistance",
        "imageSubRegion",
        "distanceDisplayCondition",
        "disableDepthTestDistance",
    ]

    def __init__(
        self,
        *,
        image,
        show=None,
        scale=None,
        horizontalOrigin=None,
        verticalOrigin=None,
    ):
        if isinstance(image, str):
            image = Uri(uri=image)
        self._image = image
        self._show = show
        self._scale = scale
        self._horizontal_origin = horizontalOrigin
        self._vertical_origin = verticalOrigin

    @property
    def show(self):
        """Whether or not the billboard is shown."""
        return self._show

    @property
    def image(self):
        """The URI of the image displayed on the billboard.

        For broadest client compatibility,
        the URI should be accessible via Cross-Origin Resource Sharing (CORS).
        The URI may also be a data URI.
        """
        return self._image

    @property
    def scale(self):
        """The scale of the billboard.

        The scale is multiplied with the pixel size of the billboard's image.
        For example, if the scale is 2.0,
        the billboard will be rendered with twice the number of pixels,
        in each direction, of the image.

        """
        return self._scale


# noinspection PyPep8Naming
class Clock(BaseCZMLObject):
    """Initial settings for a simulated clock when a document is loaded.

    The start and stop time are configured using the interval property.

    """

    KNOWN_PROPERTIES = ["currentTime", "multiplier", "range", "step"]

    def __init__(
        self,
        *,
        currentTime=None,
        multiplier=1.0,
        range=ClockRanges.LOOP_STOP,
        step=ClockSteps.SYSTEM_CLOCK_MULTIPLIER,
    ):
        self._current_time = currentTime
        self._multiplier = multiplier
        self._range = range
        self._step = step

    @property
    def currentTime(self):
        """The current time, specified in ISO8601 format."""
        return self._current_time

    @property
    def multiplier(self):
        """The multiplier.

        When step is set to TICK_DEPENDENT,
        this is the number of seconds to advance each tick.
        When step is set to SYSTEM_CLOCK_DEPENDENT,
        this is multiplied by the elapsed system time between ticks.
        This value is ignored in SYSTEM_CLOCK mode.

        """
        return self._multiplier

    @property
    def range(self):
        """The behavior when the current time reaches its start or end times."""
        return self._range

    @property
    def step(self):
        """How the current time advances each tick."""
        return self._step


# noinspection PyPep8Naming
class Path(BaseCZMLObject):
    """A path, which is a polyline defined by the motion of an object over time.

    The possible vertices of the path are specified by the position property.
    Note that because clients cannot render a truly infinite path,
    the path must be limited,
    either by defining availability for this object,
    or by using the leadTime and trailTime properties.

    """

    KNOWN_PROPERTIES = [
        "show",
        "leadTime",
        "trailTime",
        "width",
        "resolution",
        "material",
        "distanceDisplayCondition",
    ]

    def __init__(
        self, *, show=True, leadTime=None, trailTime=None, width=1.0, resolution=60.0
    ):
        self._show = show
        self._lead_time = leadTime
        self._trail_time = trailTime
        self._width = width
        self._resolution = resolution

    @property
    def show(self):
        """Whether or not the path is shown."""
        return self._show

    @property
    def leadTime(self):
        """The time ahead of the animation time, in seconds, to show the path.

        The time will be limited to not exceed the object's availability.
        By default, the value is unlimited,
        which effectively results in drawing the entire available path of the object.

        """
        return self._lead_time

    @property
    def trailTime(self):
        """The time behind the animation time, in seconds, to show the path.

        The time will be limited to not exceed the object's availability.
        By default, the value is unlimited,
        which effectively results in drawing the entire available path of the object.

        """
        return self._trail_time

    @property
    def width(self):
        """The width of the path line."""
        return self._width

    @property
    def resolution(self):
        """The maximum step-size, in seconds, used to sample the path.

        If the position property has data points
        farther apart than resolution specifies,
        additional samples will be computed,
        creating a smoother path.

        """
        return self._resolution


# noinspection PyPep8Naming
class Label(BaseCZMLObject, HasAlignment):
    """A string of text."""

    KNOWN_PROPERTIES = [
        "show",
        "text",
        "style",
        "scale",
        "showBackground",
        "backgroundColor",
        "backgroundPadding",
        "pixelOffset",
        "eyeOffset",
        "horizontalOrigin",
        "verticalOrigin",
        "heightReference",
        "fillColor",
        "outlineColor",
        "outlineWidth",
        "translucencyByDistance",
        "pixelOffsetScaleByDistance",
        "scaleByDistance",
        "distanceDisplayCondition",
        "disableDepthTestDistance",
    ]

    def __init__(
        self,
        *,
        show=True,
        text=None,
        style=LabelStyles.FILL,
        scale=None,
        showBackground=None,
        horizontalOrigin=None,
        verticalOrigin=None,
        outlineWidth=1.0,
    ):
        self._show = show
        self._text = text
        self._style = style
        self._scale = scale
        self._show_background = showBackground
        self._horizontal_origin = horizontalOrigin
        self._vertical_origin = verticalOrigin
        self._outline_width = outlineWidth

    @property
    def show(self):
        """Whether or not the label is shown."""
        return self._show

    @property
    def text(self):
        """The text displayed by the label.

        The newline character (\n) indicates line breaks.

        """
        return self._text

    @property
    def style(self):
        """The style of the label."""
        return self._style

    @property
    def scale(self):
        """The scale of the label.

        The scale is multiplied with the pixel size of the label's text.
        For example, if the scale is 2.0,
        the label will be rendered with twice the number of pixels,
        in each direction, of the text.

        """
        return self._scale

    @property
    def showBackground(self):
        """Whether or not a background behind the label is shown."""
        return self._show_background

    @property
    def outlineWidth(self):
        """The outline width of the label."""
        return self._outline_width
