U
    hC                     @   sh   d Z ddlmZ ddlmZ ddlmZ ddlm	Z	 G dd de	Z
G dd	 d	e	ZG d
d de	ZdS )aD  
Channel Core Models

This module contains the fundamental channel-related models that form
the backbone of the channel management system.

Models:
    - ChannelZone: Geographic zones for channel broadcasting
    - ChannelCodec: Video/Audio codec configurations
    - Channel: Main channel model with comprehensive metadata
    )models)timezone)gettext_lazy)	BaseModelc                   @   s   e Zd ZdZejdededdZejddeded	d
Zej	dededdZ
ejddededdZejdededdZG dd dZdd Zdd ZdS )ChannelZonea  
    Geographic zones for channel broadcasting.
    
    Represents different geographic regions where channels can broadcast,
    each with their own timezone and configuration settings.
    
    Attributes:
        name (str): Human-readable name of the zone
        code (str): Unique code identifier for the zone
        description (str): Optional detailed description
        timezone (str): Timezone identifier for the zone
        is_active (bool): Whether the zone is currently active
        
    Relationships:
        - channels: Many-to-many with Channel through ChannelZoneRelation
        
    Example:
        >>> zone = ChannelZone.objects.create(
        ...     name="North America East",
        ...     code="NAE",
        ...     timezone="America/New_York"
        ... )
       z	Zone Namez*Human-readable name of the geographic zone
max_lengthverbose_name	help_text
   Tz	Zone Codez8Unique identifier code for the zone (e.g., "NAE", "EUR")r	   uniquer
   r   Descriptionz2Optional detailed description of the zone coverageblankr
   r   2   UTCZTimezonez?Timezone identifier (e.g., "America/New_York", "Europe/London"))r	   defaultr
   r   z	Is Activez3Whether this zone is currently accepting broadcastsr   r
   r   c                   @   s&   e Zd ZdZdgZedZedZdS )zChannelZone.MetaZchannel_zonesnamezChannel ZonezChannel ZonesN__name__
__module____qualname__db_tableordering_r
   verbose_name_plural r   r   8/var/www/html/Focus/src/apps/channels/models/channels.pyMetaI   s   r!   c                 C   s   | j  d| j dS )N ())r   codeselfr   r   r    __str__O   s    zChannelZone.__str__c                 C   s   | j jdd S )z
        Get the number of active channels in this zone.
        
        Returns:
            int: Number of active channels broadcasting in this zone
        active)status)channelsfiltercountr%   r   r   r    get_active_channels_countR   s    z%ChannelZone.get_active_channels_countN)r   r   r   __doc__r   	CharFieldr   r   r$   	TextFielddescriptionr   BooleanField	is_activer!   r'   r-   r   r   r   r    r      s>   r   c                   @   s   e Zd ZdZejdededdZejdededdZejded	ed
dZ	ejddededdZ
ejededdZejddddededdZejedededdZG dd dZdd Zdd  Zd!d" Zd#S )$ChannelCodecaR  
    Video and audio codec configurations for channels.
    
    Defines encoding parameters, quality settings, and FFmpeg options
    for different streaming scenarios and quality requirements.
    
    Attributes:
        name (str): Human-readable codec configuration name
        video_codec (str): Video codec identifier (e.g., "h264", "h265")
        audio_codec (str): Audio codec identifier (e.g., "aac", "mp3")
        resolution (str): Video resolution (e.g., "1920x1080", "1280x720")
        bitrate (int): Bitrate in kbps
        frame_rate (decimal): Frame rate in fps
        ffmpeg_options (dict): Additional FFmpeg encoding options
        
    Relationships:
        - channels: One-to-many (default codec for channels)
        - zone_relations: One-to-many (zone-specific codec overrides)
        
    Example:
        >>> codec = ChannelCodec.objects.create(
        ...     name="HD H264 AAC",
        ...     video_codec="h264",
        ...     audio_codec="aac",
        ...     resolution="1920x1080",
        ...     bitrate=5000,
        ...     frame_rate=29.97
        ... )
    d   z
Codec Namez0Human-readable name for this codec configurationr   r   zVideo Codecz.Video codec identifier (h264, h265, vp9, etc.)zAudio Codecz-Audio codec identifier (aac, mp3, opus, etc.)   TZ
Resolutionz9Video resolution in WIDTHxHEIGHT format (e.g., 1920x1080)r	   r   r
   r   ZBitratezTarget bitrate in kbps)r
   r         z
Frame Ratez-Target frame rate in fps (e.g., 29.97, 25.00))
max_digitsdecimal_placesnullr   r
   r   zFFmpeg Optionsz1Additional FFmpeg encoding options as JSON object)r   r   r
   r   c                   @   s&   e Zd ZdZdgZedZedZdS )zChannelCodec.MetaZchannel_codecsr   zChannel CodeczChannel CodecsNr   r   r   r   r    r!      s   r!   c                 C   s   | j  d| j d| j dS )Nr"   /r#   )r   video_codecaudio_codecr%   r   r   r    r'      s    zChannelCodec.__str__c                 C   sX   | j s
dS d| j kr(t| j dd nd}|dkr8dS |dkrDdS |dkrPd	S d
S dS )z
        Determine quality profile based on resolution and bitrate.
        
        Returns:
            str: Quality profile (SD, HD, FHD, 4K)
        Unknownxr   i   Z4Ki  ZFHDi   ZHDZSDN)
resolutionintsplit)r&   widthr   r   r    get_quality_profile   s    "z ChannelCodec.get_quality_profilec                 C   s   | j d d S )z
        Estimate required bandwidth in Mbps.
        
        Returns:
            float: Estimated bandwidth requirement in Mbps
        g333333?i  )bitrater%   r   r   r    estimate_bandwidth_mbps   s    z$ChannelCodec.estimate_bandwidth_mbpsN)r   r   r   r.   r   r/   r   r   r>   r?   rB   PositiveIntegerFieldrG   DecimalFieldZ
frame_rate	JSONFielddictZffmpeg_optionsr!   r'   rF   rH   r   r   r   r    r4   \   sX   r4   c                   @   sv  e Zd ZdZdedfdedfdedfded	fd
edfdedfgZdedfdedfdedfdedfgZejdededdZ	ejddededdZ
ejdeded dZejdeded!ed"d#Zejdeded$ed%d#Zejed&d'ded(ed)d*Zejd+dded,ed-d.Zejded/ed0d1Zejded2ed3d1Zejd4ded5ed6d7Zejd4ded8ed9d7Zejd:ded;ed<d7Zejded=ed>d?Zejdded@edAdBZejdedCedDd?ZG dEdF dFZdGdH Z e!dIdJ Z"d`dKdLZ#dMdN Z$dOdP Z%dQdR Z&dSdT Z'dadVdWZ(dXdY Z)dZd[ Z*d\d] Z+d^d_ Z,dUS )bChannela  
    Television channels with comprehensive metadata and relationships.
    
    Represents individual TV channels with their broadcasting details,
    network affiliations, geographic coverage, and advertising inventory.
    Each channel can broadcast in multiple zones with zone-specific configurations.
    
    Attributes:
        name (str): Full channel name
        display_name (str): Call sign or short identifier
        channel_number (str): Channel number in listings
        channel_type (str): Broadcasting technology type
        status (str): Current operational status
        logo (ImageField): Channel logo/branding image
        description (str): Channel description
        website (str): Official website URL
        language (str): Primary broadcast language
        category (str): Content category
        target_audience (str): Target demographic
        supports_dai (bool): Dynamic Ad Insertion support
        max_ad_duration (int): Maximum ad break duration in seconds
        min_ad_gap (int): Minimum gap between ads in seconds
        last_health_check (datetime): Last health monitoring check
        is_online (bool): Current online status
        
    Relationships:
        - zones: Many-to-many through ChannelZoneRelation
        - codec: Foreign key to default ChannelCodec
        - programs: One-to-many with EPGProgram
        - jingles: One-to-many with Jingle
        - schedules: One-to-many with ChannelSchedule
        - jingle_detections: One-to-many with JingleDetection
        
    Example:
        >>> channel = Channel.objects.create(
        ...     name="Example News Network",
        ...     display_name="ENN",
        ...     channel_number="24.1",
        ...     channel_type="cable",
        ...     category="News"
        ... )
    ZterrestrialzTerrestrial/Over-the-AirZcablezCable ChannelZ	satellitezSatellite ChannelZiptvzIPTV Channel	streamingzStreaming ChannelradiozRadio Stationr(   ActiveinactiveInactiveZmaintenanceZMaintenanceZtestingZTesting   zChannel Namez,Full official name of the television channelr   r6   Tz	Call Signz@Official call sign or short identifier (e.g., "WABC-TV", "ESPN")r   zChannel Numberz@Channel number in cable/satellite listings (e.g., "7.1", "ESPN")zChannel Typez/Broadcasting technology and distribution method)r	   choicesr   r
   r   zChannel Statusz)Current operational status of the channelChannelZoneRelationr*   zBroadcasting ZoneszTGeographic zones where this channel is available (can be added later during editing))throughrelated_namer   r
   r   zchannels/logos/zChannel LogozChannel logo or branding image)	upload_tor   r<   r
   r   zChannel Descriptionz0Brief description of the channel and its contentr   zOfficial WebsitezChannel's official website URL   zPrimary Languagez%Primary language of broadcast contentr7   zContent Categoryz<Primary content category (News, Sports, Entertainment, etc.)r5   zTarget Audiencez<Primary target demographic (Children, Adults, Seniors, etc.)zSupports DAIz1Whether the channel supports Dynamic Ad Insertionr   zLast Health Checkz4Timestamp of the most recent health monitoring check)r<   r   r
   r   z	Is Onlinez,Current online/offline status of the channelc                   @   sT   e Zd ZdZddgZedZedZej	ddgdej	d	d
gdej	dgdgZ
dS )zChannel.Metar*   channel_numberr   rM   ZChannelsr)   	is_online)fieldschannel_typecategorylast_health_checkN)r   r   r   r   r   r   r
   r   r   Indexindexesr   r   r   r    r!   o  s   r!   c                 C   s*   | j r| j  d| jp| j S | jp(| jS )Nz. )rZ   display_namer   r%   r   r   r    r'   z  s    zChannel.__str__c                 C   s   | j dko| jS )z
        Check if channel is currently active and broadcasting.
        
        Returns:
            bool: True if channel is active and online
        r(   )r)   r[   r%   r   r   r    r3     s    zChannel.is_activec                 C   s$   || _ t | _| jddgd dS )z
        Update channel health monitoring status.
        
        Args:
            is_online (bool): Current online status
        r[   r_   )update_fieldsN)r[   r   nowr_   save)r&   r[   r   r   r    update_health_status  s    
zChannel.update_health_statusc                 C   s$   z| j j|dW S    Y dS X dS )a  
        Get the zone-specific configuration for this channel.
        
        Args:
            zone (ChannelZone): The zone to get configuration for
            
        Returns:
            ChannelZoneRelation or None: Zone-specific configuration
        )zoneN)Zzone_relationsget)r&   rg   r   r   r    get_zone_relation  s    
zChannel.get_zone_relationc                 C   s    |  |}|r|jr|jS | jS )z
        Get the appropriate stream URL for a specific zone.
        
        Args:
            zone (ChannelZone): Target broadcasting zone
            
        Returns:
            str: Stream URL for the zone or default stream URL
        )ri   
stream_urlr&   rg   Zzone_relationr   r   r    get_stream_url_for_zone  s    


zChannel.get_stream_url_for_zonec                 C   s    |  |}|r|jr|jS | jS )a  
        Get the appropriate codec configuration for a specific zone.
        
        Args:
            zone (ChannelZone): Target broadcasting zone
            
        Returns:
            ChannelCodec: Codec configuration for the zone or default codec
        )ri   codecrk   r   r   r    get_codec_for_zone  s    


zChannel.get_codec_for_zonec                 C   s   | j jdddS )z
        Get all active zones where this channel broadcasts.
        
        Returns:
            QuerySet: Active ChannelZone objects
        T)Zchannelzonerelation__is_activer3   )zonesr+   r%   r   r   r    get_active_zones  s    zChannel.get_active_zonesNc	                 C   s6   ddl m}	 |	jj| ||||||||dd\}
}|
S )zN
        Add a zone to this channel with optional configuration data.
           rU   )rm   rj   backup_stream_url
vpn_config
ftp_configstandalone_vpn_configstandalone_ftp_config)channelrg   defaults)channel_relationsrU   objectsget_or_create)r&   rg   rm   rj   rs   rt   ru   Zstandalone_vpnZstandalone_ftprU   relationcreatedr   r   r    add_zone_with_config  s    
zChannel.add_zone_with_configc                 K   sp   ddl m} zF|jj| |d}| D ]\}}t||r&t||| q&|  |W S  |jk
rj   Y dS X dS )zD
        Update configuration for a specific zone relation.
        rq   rr   )rx   rg   N)	rz   rU   r{   rh   itemshasattrsetattrre   DoesNotExist)r&   rg   Zconfig_datarU   r}   fieldvaluer   r   r    update_zone_config  s    
zChannel.update_zone_configc                 C   s*   ddl m} |jj| ddddddd	S )
z?
        Get all zone configurations for this channel.
        rq   rr   )rx   rg   rm   rt   ru   rv   rw   )rz   rU   r{   r+   select_related)r&   rU   r   r   r    get_zone_configs  s        zChannel.get_zone_configsc                 C   s   |   jdd S )z_
        Check if channel has at least one complete configuration (zone + stream URL).
        F)stream_url__isnull)r   r+   existsr%   r   r   r    has_complete_config  s    zChannel.has_complete_configc                 C   s    |   jddd}dd |D S )z>
        Get all active stream URLs for this channel.
        FT)r   Zzone__is_activec                 S   s   g | ]}|j r|j qS r   )rj   ).0configr   r   r    
<listcomp>  s      z.Channel.get_active_streams.<locals>.<listcomp>)r   r+   )r&   Zconfigsr   r   r    get_active_streams  s
    zChannel.get_active_streams)T)NNNNNNN)-r   r   r   r.   r   ZCHANNEL_TYPESSTATUS_CHOICESr   r/   r   rb   rZ   r]   r)   ManyToManyFieldr   ro   
ImageFieldlogor0   r1   URLFieldwebsitelanguager^   Ztarget_audiencer2   Zsupports_daiDateTimeFieldr_   r[   r!   r'   propertyr3   rf   ri   rl   rn   rp   r   r   r   r   r   r   r   r   r    rM      s   ,










	

	
        

rM   N)r.   	django.dbr   django.utilsr   django.utils.translationr   r   apps.common.modelsr   r   r4   rM   r   r   r   r    <module>   s   Hp