"""
Models
======
Django database models representing the files of the GTFS Reference with all their fields

Attributes
----------
Classes
-------
Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, FareAttribute, FareRule, Shape, Frequency, Transfer, Pathway, Level, FeedInfo, LocationsGeojson, BookingRule, Translation, Attribution, LocationGroup, LocationGroupStop, RouteNetwork, Network, StopArea, Area, FareMedium, FareProduct, FareLegRule, FareTransferRule, Timeframe 
    Different files as described in the GTFS Reference
"""
from django.db import models

class Agency(models.Model):
    """
    Represents agency.txt from the GTFS Reference.
    """
    agency_id = models.CharField(max_length=255, primary_key=True)
    agency_name = models.CharField(max_length=255)
    agency_url = models.URLField()
    agency_timezone = models.CharField(max_length=255)
    agency_lang = models.CharField(max_length=2, blank=True, null=True)
    agency_phone = models.CharField(max_length=50, blank=True, null=True)
    agency_fare_url = models.URLField(blank=True, null=True)
    agency_email = models.EmailField(blank=True, null=True)

class Level(models.Model):
    """
    Represents level.txt from the GTFS Reference.
    """
    level_id = models.CharField(max_length=255, primary_key=True)
    level_index = models.FloatField()
    level_name = models.CharField(max_length=255, blank=True, null=True)

class Stop(models.Model):
    """
    Represents stop.txt from the GTFS Reference.
    """
    stop_id = models.CharField(max_length=255, primary_key=True)
    stop_code = models.CharField(max_length=50, blank=True, null=True)
    stop_name = models.CharField(max_length=255)
    stop_desc = models.TextField(blank=True, null=True)
    stop_lat = models.FloatField()
    stop_lon = models.FloatField()
    zone_id = models.CharField(max_length=255, blank=True, null=True)
    stop_url = models.URLField(blank=True, null=True)
    location_type = models.IntegerField(blank=True, null=True)
    parent_station = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
    stop_timezone = models.CharField(max_length=255, blank=True, null=True)
    wheelchair_boarding = models.IntegerField(blank=True, null=True)
    level_id = models.ForeignKey(Level, on_delete=models.SET_NULL, blank=True, null=True)
    platform_code = models.CharField(max_length=50, blank=True, null=True)

class Route(models.Model):
    """
    Represents route.txt from the GTFS Reference.
    """
    route_id = models.IntegerField(primary_key=True)
    agency_id = models.ForeignKey(Agency, on_delete=models.CASCADE, blank=True, null=True)
    route_short_name = models.CharField(max_length=50)
    route_long_name = models.CharField(max_length=255, blank=True, null=True)
    route_desc = models.TextField(blank=True, null=True)
    route_type = models.IntegerField(default=0)
    route_url = models.URLField(blank=True, null=True)
    route_color = models.CharField(max_length=6, blank=True, null=True)
    route_text_color = models.CharField(max_length=6, blank=True, null=True)
    route_sort_order = models.IntegerField(blank=True, null=True)
    continuous_pickup = models.IntegerField(blank=True, null=True)
    continuous_drop_off = models.IntegerField(blank=True, null=True)

class Shape(models.Model):
    """
    Represents shape.txt from the GTFS Reference.
    """
    shape_id = models.CharField(max_length=255)
    shape_pt_lat = models.FloatField()
    shape_pt_lon = models.FloatField()
    shape_pt_sequence = models.IntegerField()
    shape_dist_traveled = models.FloatField(blank=True, null=True)

    class Meta:
        unique_together = (('shape_id', 'shape_pt_sequence'),)

class Calendar(models.Model):
    """
    Represents calendar.txt from the GTFS Reference.
    """
    service_id = models.IntegerField()
    monday = models.BooleanField()
    tuesday = models.BooleanField()
    wednesday = models.BooleanField()
    thursday = models.BooleanField()
    friday = models.BooleanField()
    saturday = models.BooleanField()
    sunday = models.BooleanField()
    start_date = models.DateField()
    end_date = models.DateField()

class CalendarDate(models.Model):
    """
    Represents calendar_date.txt from the GTFS Reference.
    """
    service_id = models.IntegerField()
    date = models.DateField()
    exception_type = models.IntegerField()

    class Meta:
        unique_together = (('service_id', 'date'),)

class Trip(models.Model):
    """
    Represents trip.txt from the GTFS Reference.
    """
    trip_id = models.CharField(max_length=255, primary_key=True)
    route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
    service_id = models.IntegerField()
    trip_headsign = models.CharField(max_length=255, blank=True, null=True)
    trip_short_name = models.CharField(max_length=255, blank=True, null=True)
    direction_id = models.IntegerField(blank=True, null=True)
    block_id = models.CharField(max_length=255, blank=True, null=True)
    shape_id = models.ForeignKey(Shape, on_delete=models.CASCADE, blank=True)
    wheelchair_accessible = models.IntegerField(blank=True, null=True)
    bikes_allowed = models.IntegerField(blank=True, null=True)

class LocationGroup(models.Model):
    """
    Represents location_group.txt from the GTFS Reference.
    """
    location_group_id = models.CharField(max_length=255, primary_key=True)
    location_group_name = models.CharField(max_length=255)
    location_group_type = models.CharField(max_length=255)

class LocationsGeojson(models.Model):
    """
    Represents locations.geojson from the GTFS Reference.
    """
    location_id = models.CharField(max_length=255, primary_key=True)
    location_name = models.CharField(max_length=255)
    location_lat = models.FloatField()
    location_lon = models.FloatField()
    location_type = models.CharField(max_length=255)
    parent_location_id = models.CharField(max_length=255, blank=True, null=True)
    wheelchair_boarding = models.BooleanField(blank=True, null=True)

class StopTime(models.Model):
    """
    Represents stop_time.txt from the GTFS Reference.
    """
    trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
    arrival_time = models.TimeField(blank=True, null=True)
    departure_time = models.TimeField(blank=True, null=True)
    stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)
    location_group_id = models.ForeignKey(LocationGroup, on_delete=models.SET_NULL, blank=True, null=True)
    location_id = models.ForeignKey(LocationsGeojson, on_delete=models.SET_NULL, blank=True, null=True)
    stop_sequence = models.IntegerField()
    stop_headsign = models.CharField(max_length=255, blank=True, null=True)
    pickup_type = models.IntegerField(blank=True, null=True)
    drop_off_type = models.IntegerField(blank=True, null=True)
    shape_dist_traveled = models.FloatField(blank=True, null=True)
    timepoint = models.IntegerField(blank=True, null=True)

    class Meta:
        unique_together = (('trip_id', 'stop_sequence'),)

class FareAttribute(models.Model):
    """
    Represents fare_attribute.txt from the GTFS Reference.
    """
    fare_id = models.CharField(max_length=255, primary_key=True)
    price = models.FloatField()
    currency_type = models.CharField(max_length=3)
    payment_method = models.IntegerField()
    transfers = models.IntegerField()
    agency_id = models.ForeignKey(Agency, on_delete=models.CASCADE, blank=True, null=True)
    transfer_duration = models.IntegerField(blank=True, null=True)

class FareRule(models.Model):
    """
    Represents fare_rule.txt from the GTFS Reference.
    """
    fare_id = models.ForeignKey(FareAttribute, on_delete=models.CASCADE)
    route_id = models.ForeignKey(Route, on_delete=models.CASCADE, blank=True, null=True)
    origin_id = models.IntegerField(blank=True, null=True)
    destination_id = models.CharField(max_length=255, blank=True, null=True)
    contains_id = models.CharField(max_length=255, blank=True, null=True)

class Frequency(models.Model):
    """
    Represents frequency.txt from the GTFS Reference.
    """
    trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
    start_time = models.TimeField()
    end_time = models.TimeField()
    headway_secs = models.IntegerField()
    exact_times = models.IntegerField(blank=True, null=True)

class Transfer(models.Model):
    """
    Represents transfer.txt from the GTFS Reference.
    """
    from_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='transfers_from_stop')
    to_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='transfers_to_stop')
    from_route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_from_route')
    to_route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_to_route')
    from_trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_from_trip')
    to_trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True, related_name='transfers_to_trip')
    transfer_type = models.IntegerField()
    min_transfer_time = models.IntegerField(blank=True, null=True)

    class Meta:
        unique_together = (('from_stop', 'to_stop'),)

class Pathway(models.Model):
    """
    Represents lathway.txt from the GTFS Reference.
    """
    pathway_id = models.CharField(max_length=255, primary_key=True)
    from_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='pathways_from')
    to_stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE, related_name='pathways_to')
    pathway_mode = models.IntegerField()
    is_bidirectional = models.IntegerField()
    length = models.FloatField(blank=True, null=True)
    traversal_time = models.IntegerField(blank=True, null=True)
    stair_count = models.IntegerField(blank=True, null=True)
    max_slope = models.FloatField(blank=True, null=True)
    min_width = models.FloatField(blank=True, null=True)
    signposted_as = models.CharField(max_length=255, blank=True, null=True)
    reversed_signposted_as = models.CharField(max_length=255, blank=True, null=True)

class FeedInfo(models.Model):
    """
    Represents feed_info.txt from the GTFS Reference.
    """
    feed_publisher_name = models.CharField(max_length=255)
    feed_publisher_url = models.URLField()
    feed_lang = models.CharField(max_length=255)
    default_lang = models.CharField(max_length=255, blank=True, null=True)
    feed_start_date = models.DateField(blank=True, null=True)
    feed_end_date = models.DateField(blank=True, null=True)
    feed_version = models.CharField(max_length=255, blank=True, null=True)
    feed_contact_email = models.EmailField(blank=True, null=True)
    feed_contact_url = models.URLField(blank=True, null=True)
    feed_id = models.BigAutoField(primary_key=True)

class BookingRule(models.Model):
    """
    Represents booking_rule.txt from the GTFS Reference.
    """
    booking_rule_id = models.CharField(max_length=255, primary_key=True)
    trip_id = models.ForeignKey(Trip, on_delete=models.CASCADE)
    start_time = models.TimeField(blank=True, null=True)
    end_time = models.TimeField(blank=True, null=True)
    booking_type = models.CharField(max_length=255)
    rule_criteria = models.TextField(blank=True, null=True)
    booking_rule_instructions = models.TextField(blank=True, null=True)

class Translation(models.Model):
    """
    Represents translation.txt from the GTFS Reference.
    """
    table_name = models.CharField(max_length=255)
    field_name = models.CharField(max_length=255)
    language = models.CharField(max_length=2)
    translation = models.TextField()

class Attribution(models.Model):
    """
    Represents attribution.txt from the GTFS Reference.
    """
    attribution_id = models.BigAutoField(primary_key=True)
    agency_id = models.ForeignKey(Agency, on_delete=models.SET_NULL, blank=True, null=True)
    route_id = models.ForeignKey(Route, on_delete=models.SET_NULL, blank=True, null=True)
    trip_id = models.ForeignKey(Trip, on_delete=models.SET_NULL, blank=True, null=True)
    attribution_name = models.CharField(max_length=255)
    attribution_url = models.URLField()
    attribution_email = models.EmailField(blank=True, null=True)
    attribution_phone = models.CharField(max_length=50, blank=True, null=True)

class LocationGroupStop(models.Model):
    """
    Represents location_groupStop.txt from the GTFS Reference.
    """
    location_group_id = models.ForeignKey(LocationGroup, on_delete=models.CASCADE)
    stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)

class Network(models.Model):
    """
    Represents network.txt from the GTFS Reference.
    """
    network_id = models.CharField(max_length=255, primary_key=True)
    network_name = models.CharField(max_length=255)

class RouteNetwork(models.Model):
    """
    Represents route_network.txt from the GTFS Reference.
    """
    route_network_id = models.CharField(max_length=255, primary_key=True)
    route_network_name = models.CharField(max_length=255)
    network_id = models.ForeignKey(Network, on_delete=models.CASCADE)
    route_id = models.ForeignKey(Route, on_delete=models.CASCADE)

class Area(models.Model):
    """
    Represents area.txt from the GTFS Reference.
    """
    area_id = models.CharField(max_length=255, primary_key=True)
    area_name = models.CharField(max_length=255)
    area_description = models.TextField(blank=True, null=True)

class StopArea(models.Model):
    """
    Represents stop_area.txt from the GTFS Reference.
    """
    stop_area_id = models.CharField(max_length=255, primary_key=True)
    stop_area_name = models.CharField(max_length=255)
    stop_area_description = models.TextField(blank=True, null=True)
    area_id = models.ForeignKey(Area, on_delete=models.CASCADE)
    stop_id = models.ForeignKey(Stop, on_delete=models.CASCADE)

class FareMedium(models.Model):
    """
    Represents fare_medium.txt from the GTFS Reference.
    """
    fare_media_id = models.CharField(max_length=255, primary_key=True)
    fare_media_name = models.CharField(max_length=255)
    fare_media_description = models.TextField(blank=True, null=True)

class FareProduct(models.Model):
    """
    Represents fare_product.txt from the GTFS Reference.
    """
    fare_product_id = models.BigAutoField(primary_key=True)
    fare_product_name = models.CharField(max_length=255)
    fare_product_description = models.TextField(blank=True, null=True)
    amount = models.FloatField()
    curreny = models.CharField(max_length=64)

class Timeframe(models.Model):
    """
    Represents timeframe.txt from the GTFS Reference.
    """
    timeframe_group_id = models.IntegerField(primary_key=True)
    service_id = models.IntegerField()
    start_date = models.DateField()
    end_date = models.DateField()
    start_time = models.TimeField()
    end_time = models.TimeField()

class FareLegRule(models.Model):
    """
    Represents fare_legRule.txt from the GTFS Reference.
    """
    fare_leg_rule_id = models.CharField(max_length=255, primary_key=True)
    fare_leg_rule_name = models.CharField(max_length=255)
    fare_leg_rule_description = models.TextField(blank=True, null=True)
    network_id = models.ForeignKey(Network, blank=True, null=True, on_delete=models.SET_NULL)
    from_area_id = models.ForeignKey(Area, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_from_area')
    to_area_id = models.ForeignKey(Area, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_to_area')
    from_timeframe_group_id = models.ForeignKey(Timeframe, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_from_timeframe')
    to_timeframe_group_id = models.ForeignKey(Timeframe, blank=True, null=True, on_delete=models.SET_NULL, related_name='farelegrule_to_timeframe')
    fare_product_id = models.ForeignKey(FareProduct, on_delete=models.CASCADE)

class FareTransferRule(models.Model):
    """
    Represents faretransfer_rule.txt from the GTFS Reference.
    """
    fare_transfer_rule_id = models.CharField(max_length=255, primary_key=True)
    fare_transfer_rule_name = models.CharField(max_length=255)
    fare_transfer_rule_description = models.TextField(blank=True, null=True)
    from_leg_group_id = models.IntegerField(blank=True, null=True)
    to_leg_group_id = models.IntegerField(blank=True, null=True)
    fare_product_id = models.ForeignKey(FareProduct, on_delete=models.SET_NULL, blank=True, null=True)
    


