# pylint: disable=line-too-long,useless-suppression
# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) Python Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
# pylint: disable=useless-super-delegation

import datetime
from typing import Any, Dict, List, Literal, Mapping, Optional, TYPE_CHECKING, Union, overload

from .._utils.model_base import Model as _Model, rest_discriminator, rest_field
from ._enums import ExperimentMetricType

if TYPE_CHECKING:
    from .. import models as _models


class AggregatedValue(_Model):
    """An event property value aggregated by a metric.

    :ivar event_name: The name of the event. Required.
    :vartype event_name: str
    :ivar filter: [Optional] A condition to filter events.
    :vartype filter: str
    :ivar event_property: The key of the event property to aggregate. Required.
    :vartype event_property: str
    """

    event_name: str = rest_field(name="eventName", visibility=["read", "create", "update", "delete", "query"])
    """The name of the event. Required."""
    filter: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """[Optional] A condition to filter events."""
    event_property: str = rest_field(name="eventProperty", visibility=["read", "create", "update", "delete", "query"])
    """The key of the event property to aggregate. Required."""

    @overload
    def __init__(
        self,
        *,
        event_name: str,
        event_property: str,
        filter: Optional[str] = None,  # pylint: disable=redefined-builtin
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)


class ExperimentMetricDefinition(_Model):
    """The metric definition, which determines how the metric value is calculated from event data.

    You probably want to use the sub-classes and not this class directly. Known sub-classes are:
    AverageMetricDefinition, EventCountMetricDefinition, EventRateMetricDefinition,
    PercentileMetricDefinition, SumMetricDefinition, UserCountMetricDefinition,
    UserRateMetricDefinition

    :ivar type: Discriminator property for ExperimentMetricDefinition. Required. Known values are:
     "EventCount", "UserCount", "EventRate", "UserRate", "Sum", "Average", and "Percentile".
    :vartype type: str or ~azure.onlineexperimentation.models.ExperimentMetricType
    """

    __mapping__: Dict[str, _Model] = {}
    type: str = rest_discriminator(name="type")
    """Discriminator property for ExperimentMetricDefinition. Required. Known values are:
     \"EventCount\", \"UserCount\", \"EventRate\", \"UserRate\", \"Sum\", \"Average\", and
     \"Percentile\"."""

    @overload
    def __init__(
        self,
        *,
        type: str,
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)


class AverageMetricDefinition(ExperimentMetricDefinition, discriminator="Average"):
    """The definition of an Average metric definition. Calculates the average value of a specified
    event property.

    :ivar type: The type of metric. Required. Calculates the average value of a specified event
     property.
    :vartype type: str or ~azure.onlineexperimentation.models.AVERAGE
    :ivar value: The value to aggregate. Required.
    :vartype value: ~azure.onlineexperimentation.models.AggregatedValue
    """

    type: Literal[ExperimentMetricType.AVERAGE] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"])  # type: ignore
    """The type of metric. Required. Calculates the average value of a specified event property."""
    value: "_models.AggregatedValue" = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """The value to aggregate. Required."""

    @overload
    def __init__(
        self,
        *,
        value: "_models.AggregatedValue",
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, type=ExperimentMetricType.AVERAGE, **kwargs)


class DiagnosticDetail(_Model):
    """Diagnostic details for validation errors.

    :ivar message: A human-readable error message. Required.
    :vartype message: str
    :ivar code: The diagnostic error code. Required. Known values are: "FailedSchemaValidation",
     "InvalidEventCondition", "UnsupportedEventCondition", and "InvalidExperimentMetricDefinition".
    :vartype code: str or ~azure.onlineexperimentation.models.DiagnosticCode
    """

    message: str = rest_field(visibility=["read"])
    """A human-readable error message. Required."""
    code: Union[str, "_models.DiagnosticCode"] = rest_field(visibility=["read"])
    """The diagnostic error code. Required. Known values are: \"FailedSchemaValidation\",
     \"InvalidEventCondition\", \"UnsupportedEventCondition\", and
     \"InvalidExperimentMetricDefinition\"."""


class EventCountMetricDefinition(ExperimentMetricDefinition, discriminator="EventCount"):
    """The definition of an EventCount metric definition. Counts the occurrences of a specified event.

    :ivar type: The type of metric. Required. Counts the occurrences of an event. Experiment
     analysis accounts for unequal traffic allocation.
    :vartype type: str or ~azure.onlineexperimentation.models.EVENT_COUNT
    :ivar event: Event to observe. Required.
    :vartype event: ~azure.onlineexperimentation.models.ObservedEvent
    """

    type: Literal[ExperimentMetricType.EVENT_COUNT] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"])  # type: ignore
    """The type of metric. Required. Counts the occurrences of an event. Experiment analysis accounts
     for unequal traffic allocation."""
    event: "_models.ObservedEvent" = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """Event to observe. Required."""

    @overload
    def __init__(
        self,
        *,
        event: "_models.ObservedEvent",
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, type=ExperimentMetricType.EVENT_COUNT, **kwargs)


class EventRateMetricDefinition(ExperimentMetricDefinition, discriminator="EventRate"):
    """The definition of an EventRate metric definition. Calculates the percentage of events
    satisfying a specified condition.

    :ivar type: The type of metric. Required. Calculates the percentage of events that satisfy a
     specified condition.
    :vartype type: str or ~azure.onlineexperimentation.models.EVENT_RATE
    :ivar event: Event to observe as the rate denominator. Required.
    :vartype event: ~azure.onlineexperimentation.models.ObservedEvent
    :ivar rate_condition: The event contributes to the rate numerator if it satisfies this
     condition. Required.
    :vartype rate_condition: str
    """

    type: Literal[ExperimentMetricType.EVENT_RATE] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"])  # type: ignore
    """The type of metric. Required. Calculates the percentage of events that satisfy a specified
     condition."""
    event: "_models.ObservedEvent" = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """Event to observe as the rate denominator. Required."""
    rate_condition: str = rest_field(name="rateCondition", visibility=["read", "create", "update", "delete", "query"])
    """The event contributes to the rate numerator if it satisfies this condition. Required."""

    @overload
    def __init__(
        self,
        *,
        event: "_models.ObservedEvent",
        rate_condition: str,
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, type=ExperimentMetricType.EVENT_RATE, **kwargs)


class ExperimentMetric(_Model):
    """Defines experiment metric metadata and computation details.

    :ivar id: Identifier for this experiment metric. Must start with a lowercase letter and contain
     only lowercase letters, numbers, and underscores. Required.
    :vartype id: str
    :ivar lifecycle: Determines whether it is included in experiment analysis. Required. Known
     values are: "Active" and "Inactive".
    :vartype lifecycle: str or ~azure.onlineexperimentation.models.LifecycleStage
    :ivar display_name: A user-friendly display name for the experiment metric shown in reports and
     dashboards. Required.
    :vartype display_name: str
    :ivar description: A detailed description of the experiment metric. Required.
    :vartype description: str
    :ivar categories: Categories associated with the experiment metric. Used for organizing and
     filtering metrics. Required.
    :vartype categories: list[str]
    :ivar desired_direction: The desired direction for changes in the metric value. Required. Known
     values are: "Increase", "Decrease", and "Neutral".
    :vartype desired_direction: str or ~azure.onlineexperimentation.models.DesiredDirection
    :ivar definition: The metric definition specifying how the metric value is calculated from
     event data. Required.
    :vartype definition: ~azure.onlineexperimentation.models.ExperimentMetricDefinition
    :ivar etag: ETag of the experiment metric. Required.
    :vartype etag: str
    :ivar last_modified_at: The timestamp (UTC) of the last modification to the experiment metric
     resource. Required.
    :vartype last_modified_at: ~datetime.datetime
    """

    id: str = rest_field(visibility=["read"])
    """Identifier for this experiment metric. Must start with a lowercase letter and contain only
     lowercase letters, numbers, and underscores. Required."""
    lifecycle: Union[str, "_models.LifecycleStage"] = rest_field(
        visibility=["read", "create", "update", "delete", "query"]
    )
    """Determines whether it is included in experiment analysis. Required. Known values are:
     \"Active\" and \"Inactive\"."""
    display_name: str = rest_field(name="displayName", visibility=["read", "create", "update", "delete", "query"])
    """A user-friendly display name for the experiment metric shown in reports and dashboards.
     Required."""
    description: str = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """A detailed description of the experiment metric. Required."""
    categories: List[str] = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """Categories associated with the experiment metric. Used for organizing and filtering metrics.
     Required."""
    desired_direction: Union[str, "_models.DesiredDirection"] = rest_field(
        name="desiredDirection", visibility=["read", "create", "update", "delete", "query"]
    )
    """The desired direction for changes in the metric value. Required. Known values are:
     \"Increase\", \"Decrease\", and \"Neutral\"."""
    definition: "_models.ExperimentMetricDefinition" = rest_field(
        visibility=["read", "create", "update", "delete", "query"]
    )
    """The metric definition specifying how the metric value is calculated from event data. Required."""
    etag: str = rest_field(name="eTag", visibility=["read"])
    """ETag of the experiment metric. Required."""
    last_modified_at: datetime.datetime = rest_field(name="lastModifiedAt", visibility=["read"], format="rfc3339")
    """The timestamp (UTC) of the last modification to the experiment metric resource. Required."""

    @overload
    def __init__(
        self,
        *,
        lifecycle: Union[str, "_models.LifecycleStage"],
        display_name: str,
        description: str,
        categories: List[str],
        desired_direction: Union[str, "_models.DesiredDirection"],
        definition: "_models.ExperimentMetricDefinition",
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)


class ExperimentMetricValidationResult(_Model):
    """The result of validating an experiment metric.

    :ivar is_valid: Indicates whether the experiment metric is valid. Required.
    :vartype is_valid: bool
    :ivar diagnostics: Diagnostic details from the validation process. Required.
    :vartype diagnostics: list[~azure.onlineexperimentation.models.DiagnosticDetail]
    """

    is_valid: bool = rest_field(name="isValid", visibility=["read", "create", "update", "delete", "query"])
    """Indicates whether the experiment metric is valid. Required."""
    diagnostics: List["_models.DiagnosticDetail"] = rest_field(visibility=["read"])
    """Diagnostic details from the validation process. Required."""

    @overload
    def __init__(
        self,
        *,
        is_valid: bool,
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)


class ObservedEvent(_Model):
    """An event observed by a metric.

    :ivar event_name: The name of the event. Required.
    :vartype event_name: str
    :ivar filter: [Optional] A condition to filter events.
    :vartype filter: str
    """

    event_name: str = rest_field(name="eventName", visibility=["read", "create", "update", "delete", "query"])
    """The name of the event. Required."""
    filter: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """[Optional] A condition to filter events."""

    @overload
    def __init__(
        self,
        *,
        event_name: str,
        filter: Optional[str] = None,  # pylint: disable=redefined-builtin
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)


class PercentileMetricDefinition(ExperimentMetricDefinition, discriminator="Percentile"):
    """The definition of a Percentile metric definition. Calculates a specified percentile of an event
    property.

    :ivar type: The type of metric. Required. Calculates a specified percentile of an event
     property.
    :vartype type: str or ~azure.onlineexperimentation.models.PERCENTILE
    :ivar value: The value to aggregate, including the event name and property to measure.
     Required.
    :vartype value: ~azure.onlineexperimentation.models.AggregatedValue
    :ivar percentile: The percentile to measure. Required.
    :vartype percentile: float
    """

    type: Literal[ExperimentMetricType.PERCENTILE] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"])  # type: ignore
    """The type of metric. Required. Calculates a specified percentile of an event property."""
    value: "_models.AggregatedValue" = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """The value to aggregate, including the event name and property to measure. Required."""
    percentile: float = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """The percentile to measure. Required."""

    @overload
    def __init__(
        self,
        *,
        value: "_models.AggregatedValue",
        percentile: float,
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, type=ExperimentMetricType.PERCENTILE, **kwargs)


class SumMetricDefinition(ExperimentMetricDefinition, discriminator="Sum"):
    """The definition of a Sum metric definition. Calculates the sum of a specified event property.
    Experiment analysis accounts for unequal traffic allocation.

    :ivar type: The type of metric. Required. Calculates the sum of a specified event property.
     Experiment analysis accounts for unequal traffic allocation.
    :vartype type: str or ~azure.onlineexperimentation.models.SUM
    :ivar value: The value to aggregate. Required.
    :vartype value: ~azure.onlineexperimentation.models.AggregatedValue
    """

    type: Literal[ExperimentMetricType.SUM] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"])  # type: ignore
    """The type of metric. Required. Calculates the sum of a specified event property. Experiment
     analysis accounts for unequal traffic allocation."""
    value: "_models.AggregatedValue" = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """The value to aggregate. Required."""

    @overload
    def __init__(
        self,
        *,
        value: "_models.AggregatedValue",
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, type=ExperimentMetricType.SUM, **kwargs)


class UserCountMetricDefinition(ExperimentMetricDefinition, discriminator="UserCount"):
    """The definition of a UserCount metric definition. Counts unique users who encounter a specified
    event.

    :ivar type: The type of metric. Required. Counts the number of unique users who encounter an
     event. Experiment analysis accounts for unequal traffic allocation.
    :vartype type: str or ~azure.onlineexperimentation.models.USER_COUNT
    :ivar event: Event to observe. Required.
    :vartype event: ~azure.onlineexperimentation.models.ObservedEvent
    """

    type: Literal[ExperimentMetricType.USER_COUNT] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"])  # type: ignore
    """The type of metric. Required. Counts the number of unique users who encounter an event.
     Experiment analysis accounts for unequal traffic allocation."""
    event: "_models.ObservedEvent" = rest_field(visibility=["read", "create", "update", "delete", "query"])
    """Event to observe. Required."""

    @overload
    def __init__(
        self,
        *,
        event: "_models.ObservedEvent",
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, type=ExperimentMetricType.USER_COUNT, **kwargs)


class UserRateMetricDefinition(ExperimentMetricDefinition, discriminator="UserRate"):
    """The definition of a UserRate metric definition. Calculates the percentage of users who
    encounter a start event and subsequently an end event. Users must encounter events in the
    specified order.

    :ivar type: The type of metric. Required. Calculates the percentage of users who encounter a
     start event and subsequently encounter an end event. Users must encounter the start event
     before the end event to be counted.
    :vartype type: str or ~azure.onlineexperimentation.models.USER_RATE
    :ivar start_event: The start event to observe as the rate denominator. Required.
    :vartype start_event: ~azure.onlineexperimentation.models.ObservedEvent
    :ivar end_event: The end event to observe, which is a condition for the rate numerator.
     Required.
    :vartype end_event: ~azure.onlineexperimentation.models.ObservedEvent
    """

    type: Literal[ExperimentMetricType.USER_RATE] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"])  # type: ignore
    """The type of metric. Required. Calculates the percentage of users who encounter a start event
     and subsequently encounter an end event. Users must encounter the start event before the end
     event to be counted."""
    start_event: "_models.ObservedEvent" = rest_field(
        name="startEvent", visibility=["read", "create", "update", "delete", "query"]
    )
    """The start event to observe as the rate denominator. Required."""
    end_event: "_models.ObservedEvent" = rest_field(
        name="endEvent", visibility=["read", "create", "update", "delete", "query"]
    )
    """The end event to observe, which is a condition for the rate numerator. Required."""

    @overload
    def __init__(
        self,
        *,
        start_event: "_models.ObservedEvent",
        end_event: "_models.ObservedEvent",
    ) -> None: ...

    @overload
    def __init__(self, mapping: Mapping[str, Any]) -> None:
        """
        :param mapping: raw JSON to initialize the model.
        :type mapping: Mapping[str, Any]
        """

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, type=ExperimentMetricType.USER_RATE, **kwargs)
