#------------------------------------------------------------------------------
# Copyright (C) 2010 Richard Lincoln
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#------------------------------------------------------------------------------

""" An extension to the Core and Wires packages that models information for protection equipment such as relays. These entities are used within training simulators and distribution network fault location applications.
"""
#------------------------------------------------------------------------------
#  Imports:
#------------------------------------------------------------------------------

from CIM.IEC61970.Core import Equipment
from CIM.IEC61970.Core import IdentifiedObject
from CIM.IEC61970.Domain import Seconds
from CIM.IEC61970.Domain import Frequency
from CIM.IEC61970.Domain import Voltage
from CIM.IEC61970.Domain import AngleRadians
from CIM.IEC61970.Domain import CurrentFlow



from enthought.traits.api import Instance, List, Property, Int, Float, Bool
# <<< imports
# @generated
from enthought.traits.ui.api import View, Group, Item, HGroup, VGroup, Tabbed, VGrid, InstanceEditor
# >>> imports
#------------------------------------------------------------------------------
#  Trait definitions:
#------------------------------------------------------------------------------


#------------------------------------------------------------------------------
#  "FaultIndicator" class:
#------------------------------------------------------------------------------

class FaultIndicator(Equipment):
    """ A FaultIndicator is typically only an indicator (which may or may not be remotely monitored), and not a piece of equipment that actually initiates a protection event. It is used for FLISR (Fault Location, Isolation and Restoration) purposes, assisting with the dispatch of crews to 'most likely' part of the network (i.e. assists with determining circuit section where the fault most likely happened).
    """

    #--------------------------------------------------------------------------
    #  Trait definitions:
    #--------------------------------------------------------------------------

    FaultIndicatorAssets = List(Instance("CIM.IEC61968.Informative.InfAssets.FaultIndicatorAsset"))

    FaultIndicatorTypeAsset = Instance("CIM.IEC61968.Informative.InfTypeAsset.FaultIndicatorTypeAsset",
        transient=True,
        opposite="FaultIndicators",
        editor=InstanceEditor(name="_faultindicatortypeassets"))

    def _get_faultindicatortypeassets(self):
        """ Property getter.
        """
        if self.Parent is not None:
            return [e for e in self.Parent.Elements \
                if "%s.%s" % (e.__module__, e.__class__.__name__) == \
                    "CIM.IEC61968.Informative.InfTypeAsset.FaultIndicatorTypeAsset" ]
        else:
            return []

    _faultindicatortypeassets = Property(fget=_get_faultindicatortypeassets)

    #--------------------------------------------------------------------------
    #  Begin "FaultIndicator" user definitions:
    #--------------------------------------------------------------------------

    # @generated
    traits_view = View(Tabbed(
            VGroup("UUID", "description", "mRID", "name", "pathName", "localName", "aliasName", "normaIlyInService",
                label="Attributes"),
            VGroup("Parent", "ModelingAuthoritySet", "ChangeItems", "AssetRoles", "GeoLocation", "SafetyDocuments", "OutageSchedule", "Measurements", "ErpOrganisationRoles", "PSRType", "PsrLists", "PSREvent", "OperatingShare", "ScheduleSteps", "DocumentRoles", "ReportingGroup", "CircuitSections", "NetworkDataSets", "ContingencyEquipment", "CustomerAgreements", "OperationalLimitSet", "EquipmentContainer", "FaultIndicatorAssets", "FaultIndicatorTypeAsset",
                label="References", columns=2),
            dock="tab"),
        id="CIM.IEC61970.Protection.FaultIndicator",
        title="FaultIndicator",
        buttons=["OK", "Cancel", "Help"],
        resizable=False)

    #--------------------------------------------------------------------------
    #  End "FaultIndicator" user definitions:
    #--------------------------------------------------------------------------

#------------------------------------------------------------------------------
#  "SurgeProtector" class:
#------------------------------------------------------------------------------

class SurgeProtector(Equipment):
    """ Shunt device, installed on the network, usually in the proximity of electrical equipment in order to protect the said equipment against transient voltage spikes caused by lightning or switching activity.
    """

    #--------------------------------------------------------------------------
    #  Trait definitions:
    #--------------------------------------------------------------------------

    SurgeProtectorTypeAsset = Instance("CIM.IEC61968.Informative.InfTypeAsset.SurgeProtectorTypeAsset",
        transient=True,
        opposite="SurgeProtectors",
        editor=InstanceEditor(name="_surgeprotectortypeassets"))

    def _get_surgeprotectortypeassets(self):
        """ Property getter.
        """
        if self.Parent is not None:
            return [e for e in self.Parent.Elements \
                if "%s.%s" % (e.__module__, e.__class__.__name__) == \
                    "CIM.IEC61968.Informative.InfTypeAsset.SurgeProtectorTypeAsset" ]
        else:
            return []

    _surgeprotectortypeassets = Property(fget=_get_surgeprotectortypeassets)

    SurgeProtectorAsset = Instance("CIM.IEC61968.Informative.InfAssets.SurgeProtectorAsset",
        transient=True,
        opposite="SurgeProtector",
        editor=InstanceEditor(name="_surgeprotectorassets"))

    def _get_surgeprotectorassets(self):
        """ Property getter.
        """
        if self.Parent is not None:
            return [e for e in self.Parent.Elements \
                if "%s.%s" % (e.__module__, e.__class__.__name__) == \
                    "CIM.IEC61968.Informative.InfAssets.SurgeProtectorAsset" ]
        else:
            return []

    _surgeprotectorassets = Property(fget=_get_surgeprotectorassets)

    #--------------------------------------------------------------------------
    #  Begin "SurgeProtector" user definitions:
    #--------------------------------------------------------------------------

    # @generated
    traits_view = View(Tabbed(
            VGroup("UUID", "description", "mRID", "name", "pathName", "localName", "aliasName", "normaIlyInService",
                label="Attributes"),
            VGroup("Parent", "ModelingAuthoritySet", "ChangeItems", "AssetRoles", "GeoLocation", "SafetyDocuments", "OutageSchedule", "Measurements", "ErpOrganisationRoles", "PSRType", "PsrLists", "PSREvent", "OperatingShare", "ScheduleSteps", "DocumentRoles", "ReportingGroup", "CircuitSections", "NetworkDataSets", "ContingencyEquipment", "CustomerAgreements", "OperationalLimitSet", "EquipmentContainer", "SurgeProtectorTypeAsset", "SurgeProtectorAsset",
                label="References", columns=2),
            dock="tab"),
        id="CIM.IEC61970.Protection.SurgeProtector",
        title="SurgeProtector",
        buttons=["OK", "Cancel", "Help"],
        resizable=False)

    #--------------------------------------------------------------------------
    #  End "SurgeProtector" user definitions:
    #--------------------------------------------------------------------------

#------------------------------------------------------------------------------
#  "RecloseSequence" class:
#------------------------------------------------------------------------------

class RecloseSequence(IdentifiedObject):
    """ A reclose sequence (open and close) is defined for each possible reclosure of a breaker.
    """

    #--------------------------------------------------------------------------
    #  Trait definitions:
    #--------------------------------------------------------------------------

    # A breaker may have zero or more automatic reclosures after a trip occurs.
    ProtectedSwitch = Instance("CIM.IEC61970.Wires.ProtectedSwitch",
        desc="A breaker may have zero or more automatic reclosures after a trip occurs.",
        transient=True,
        opposite="RecloseSequences",
        editor=InstanceEditor(name="_protectedswitchs"))

    def _get_protectedswitchs(self):
        """ Property getter.
        """
        if self.Parent is not None:
            return [e for e in self.Parent.Elements \
                if "%s.%s" % (e.__module__, e.__class__.__name__) == \
                    "CIM.IEC61970.Wires.ProtectedSwitch" ]
        else:
            return []

    _protectedswitchs = Property(fget=_get_protectedswitchs)

    # Indicates the ordinal position of the reclose step relative to other steps in the sequence.
    recloseStep = Int(desc="Indicates the ordinal position of the reclose step relative to other steps in the sequence.")

    # Indicates the time lapse before the reclose step will execute a reclose.
    recloseDelay = Seconds(desc="Indicates the time lapse before the reclose step will execute a reclose.")

    #--------------------------------------------------------------------------
    #  Begin "RecloseSequence" user definitions:
    #--------------------------------------------------------------------------

    # @generated
    traits_view = View(Tabbed(
            VGroup("UUID", "description", "mRID", "name", "pathName", "localName", "aliasName", "recloseStep", "recloseDelay",
                label="Attributes"),
            VGroup("Parent", "ModelingAuthoritySet", "ProtectedSwitch",
                label="References"),
            dock="tab"),
        id="CIM.IEC61970.Protection.RecloseSequence",
        title="RecloseSequence",
        buttons=["OK", "Cancel", "Help"],
        resizable=False)

    #--------------------------------------------------------------------------
    #  End "RecloseSequence" user definitions:
    #--------------------------------------------------------------------------

#------------------------------------------------------------------------------
#  "ProtectionEquipment" class:
#------------------------------------------------------------------------------

class ProtectionEquipment(Equipment):
    """ An electrical device designed to respond to input conditions in a prescribed manner and after specified conditions are met to cause contact operation or similar abrupt change in associated electric control circuits, or simply to display the detected condition. Protection equipment are associated with conducting equipment and usually operate circuit breakers.
    """

    #--------------------------------------------------------------------------
    #  Trait definitions:
    #--------------------------------------------------------------------------

    # Protected switches operated by this ProtectionEquipment.
    ProtectedSwitches = List(Instance("CIM.IEC61970.Wires.ProtectedSwitch"),
        desc="Protected switches operated by this ProtectionEquipment.")

    # The Unit for the Protection Equipment.
    Unit = Instance("CIM.IEC61970.Core.Unit",
        desc="The Unit for the Protection Equipment.",
        transient=True,
        opposite="ProtectionEquipments",
        editor=InstanceEditor(name="_units"))

    def _get_units(self):
        """ Property getter.
        """
        if self.Parent is not None:
            return [e for e in self.Parent.Elements \
                if "%s.%s" % (e.__module__, e.__class__.__name__) == \
                    "CIM.IEC61970.Core.Unit" ]
        else:
            return []

    _units = Property(fget=_get_units)

    # Protection equipment may be used to protect specific Conducting Equipment. Multiple equipment may be protected or monitored by multiple protection equipment.
    ConductingEquipments = List(Instance("CIM.IEC61970.Core.ConductingEquipment"),
        desc="Protection equipment may be used to protect specific Conducting Equipment. Multiple equipment may be protected or monitored by multiple protection equipment.")

    # The maximum allowable value.
    highLimit = Float(desc="The maximum allowable value.")

    # Direction same as positive active power flow value.
    powerDirectionFlag = Bool(desc="Direction same as positive active power flow value.")

    # The minimum allowable value.
    lowLimit = Float(desc="The minimum allowable value.")

    # The time delay from detection of abnormal conditions to relay operation.
    relayDelayTime = Seconds(desc="The time delay from detection of abnormal conditions to relay operation.")

    #--------------------------------------------------------------------------
    #  Begin "ProtectionEquipment" user definitions:
    #--------------------------------------------------------------------------

    # @generated
    traits_view = View(Tabbed(
            VGroup("UUID", "description", "mRID", "name", "pathName", "localName", "aliasName", "normaIlyInService", "highLimit", "powerDirectionFlag", "lowLimit", "relayDelayTime",
                label="Attributes"),
            VGroup("Parent", "ModelingAuthoritySet", "ChangeItems", "AssetRoles", "GeoLocation", "SafetyDocuments", "OutageSchedule", "Measurements", "ErpOrganisationRoles", "PSRType", "PsrLists", "PSREvent", "OperatingShare", "ScheduleSteps", "DocumentRoles", "ReportingGroup", "CircuitSections", "NetworkDataSets", "ContingencyEquipment", "CustomerAgreements", "OperationalLimitSet", "EquipmentContainer", "ProtectedSwitches", "Unit", "ConductingEquipments",
                label="References", columns=2),
            dock="tab"),
        id="CIM.IEC61970.Protection.ProtectionEquipment",
        title="ProtectionEquipment",
        buttons=["OK", "Cancel", "Help"],
        resizable=False)

    #--------------------------------------------------------------------------
    #  End "ProtectionEquipment" user definitions:
    #--------------------------------------------------------------------------

#------------------------------------------------------------------------------
#  "SynchrocheckRelay" class:
#------------------------------------------------------------------------------

class SynchrocheckRelay(ProtectionEquipment):
    """ A device that operates when two AC circuits are within the desired limits of frequency, phase angle, and voltage, to permit or to cause the paralleling of these two circuits. Used to prevent the paralleling of non-synchronous topological islands.
    """

    #--------------------------------------------------------------------------
    #  Trait definitions:
    #--------------------------------------------------------------------------

    # The maximum allowable frequency difference across the open device
    maxFreqDiff = Frequency(desc="The maximum allowable frequency difference across the open device")

    # The maximum allowable difference voltage across the open device
    maxVoltDiff = Voltage(desc="The maximum allowable difference voltage across the open device")

    # The maximum allowable voltage vector phase angle difference across the open device
    maxAngleDiff = AngleRadians(desc="The maximum allowable voltage vector phase angle difference across the open device")

    #--------------------------------------------------------------------------
    #  Begin "SynchrocheckRelay" user definitions:
    #--------------------------------------------------------------------------

    # @generated
    traits_view = View(Tabbed(
            VGroup("UUID", "description", "mRID", "name", "pathName", "localName", "aliasName", "normaIlyInService", "highLimit", "powerDirectionFlag", "lowLimit", "relayDelayTime", "maxFreqDiff", "maxVoltDiff", "maxAngleDiff",
                label="Attributes", columns=1),
            VGroup("Parent", "ModelingAuthoritySet", "ChangeItems", "AssetRoles", "GeoLocation", "SafetyDocuments", "OutageSchedule", "Measurements", "ErpOrganisationRoles", "PSRType", "PsrLists", "PSREvent", "OperatingShare", "ScheduleSteps", "DocumentRoles", "ReportingGroup", "CircuitSections", "NetworkDataSets", "ContingencyEquipment", "CustomerAgreements", "OperationalLimitSet", "EquipmentContainer", "ProtectedSwitches", "Unit", "ConductingEquipments",
                label="References", columns=2),
            dock="tab"),
        id="CIM.IEC61970.Protection.SynchrocheckRelay",
        title="SynchrocheckRelay",
        buttons=["OK", "Cancel", "Help"],
        resizable=False)

    #--------------------------------------------------------------------------
    #  End "SynchrocheckRelay" user definitions:
    #--------------------------------------------------------------------------

#------------------------------------------------------------------------------
#  "CurrentRelay" class:
#------------------------------------------------------------------------------

class CurrentRelay(ProtectionEquipment):
    """ A device that checks current flow values in any direction or designated direction
    """

    #--------------------------------------------------------------------------
    #  Trait definitions:
    #--------------------------------------------------------------------------

    # Inverse time delay #2 for current limit #2
    timeDelay2 = Seconds(desc="Inverse time delay #2 for current limit #2")

    # Current limit #2 for inverse time pickup
    currentLimit2 = CurrentFlow(desc="Current limit #2 for inverse time pickup")

    # Current limit #3 for inverse time pickup
    currentLimit3 = CurrentFlow(desc="Current limit #3 for inverse time pickup")

    # Set true if the current relay has inverse time characteristic.
    inverseTimeFlag = Bool(desc="Set true if the current relay has inverse time characteristic.")

    # Inverse time delay #3 for current limit #3
    timeDelay3 = Seconds(desc="Inverse time delay #3 for current limit #3")

    # Current limit #1 for inverse time pickup
    currentLimit1 = CurrentFlow(desc="Current limit #1 for inverse time pickup")

    # Inverse time delay #1 for current limit #1
    timeDelay1 = Seconds(desc="Inverse time delay #1 for current limit #1")

    #--------------------------------------------------------------------------
    #  Begin "CurrentRelay" user definitions:
    #--------------------------------------------------------------------------

    # @generated
    traits_view = View(Tabbed(
            VGroup("UUID", "description", "mRID", "name", "pathName", "localName", "aliasName", "normaIlyInService", "highLimit", "powerDirectionFlag", "lowLimit", "relayDelayTime", "timeDelay2", "currentLimit2", "currentLimit3", "inverseTimeFlag", "timeDelay3", "currentLimit1", "timeDelay1",
                label="Attributes", columns=1),
            VGroup("Parent", "ModelingAuthoritySet", "ChangeItems", "AssetRoles", "GeoLocation", "SafetyDocuments", "OutageSchedule", "Measurements", "ErpOrganisationRoles", "PSRType", "PsrLists", "PSREvent", "OperatingShare", "ScheduleSteps", "DocumentRoles", "ReportingGroup", "CircuitSections", "NetworkDataSets", "ContingencyEquipment", "CustomerAgreements", "OperationalLimitSet", "EquipmentContainer", "ProtectedSwitches", "Unit", "ConductingEquipments",
                label="References", columns=2),
            dock="tab"),
        id="CIM.IEC61970.Protection.CurrentRelay",
        title="CurrentRelay",
        buttons=["OK", "Cancel", "Help"],
        resizable=False)

    #--------------------------------------------------------------------------
    #  End "CurrentRelay" user definitions:
    #--------------------------------------------------------------------------



# EOF -------------------------------------------------------------------------
