"""
Django models for storing S3 log data. The main event is :class:`S3LogRecord`.
"""
from django.db import models

class S3LoggedBucketManager(models.Manager):
    """
    Table-level operations for S3LoggedBucket model.
    """
    def get_log_buckets_to_monitor(self):
        """
        Returns which S3LoggedBucket objects the log puller should monitor
        for log keys.
        
        :rtype: QuerySet
        :returns: The S3LoggedBucket objects that should be monitored for
            log keys.
        """
        return self.filter(monitor_bucket=True)

class S3LoggedBucket(models.Model):
    """
    A bucket that is logged.
    """
    name = models.CharField(max_length=255, unique=True, db_index=True,
        help_text="The name of the bucket that is being logged. This is "\
                  "where the media that is being served resides.")
    log_bucket_name = models.CharField(max_length=255,
        help_text="The S3 bucket to monitor for log keys. This must be a "\
                  "separate bucket from the logged bucket. The contents of "\
                  "this bucket must only be log files.")
    monitor_bucket = models.BooleanField(default=True,
        help_text="When checked, pull logs from this bucket's log bucket.")

    # Custom manager.
    objects = S3LoggedBucketManager()

    def __unicode__(self):
        return "S3LoggedBucket: %s" % self.name

class S3LogRecord(models.Model):
    """
    A single log entry for a bucket in S3.
    """
    bucket_owner = models.CharField(max_length=255,
        help_text="The canonical id of the owner of the source bucket.")
    bucket = models.ForeignKey(S3LoggedBucket,
        help_text="The bucket that the request was processed against.")
    request_dtime = models.DateTimeField(
        help_text="The time at which the request was received.")
    remote_ip = models.IPAddressField(
        help_text="The apparent Internet address of the requester. "\
                  "Intermediate proxies and firewalls might obscure the "\
                  "actual address of the machine making the request.")
    requester = models.CharField(max_length=255, blank=True, null=True,
        help_text="The canonical user id of the requester, or the string "\
                  "'Anonymous' for unauthenticated requests. This "\
                  "identifier is the same one used for access control "\
                  "purposes.")
    request_id = models.CharField(max_length=255, unique=True, db_index=True,
        help_text="A string generated by Amazon S3 to uniquely identify "\
                  "each request.")
    operation = models.CharField(max_length=255,
        help_text="Either SOAP.<operation> or "\
                  "REST.<HTTP_method.resource_type>.")
    key = models.TextField(
        help_text="The 'key' part of the request, URL encoded, or '-' if "\
                  "the operation does not take a key parameter.")
    request_method = models.CharField(max_length=10, blank=True, null=True,
        help_text="The method used to retrieve the file. Typically either "\
                  "GET or POST.")
    request_uri = models.TextField(
        help_text="The Request-URI part of the HTTP request message.")
    http_version = models.CharField(max_length=15, blank=True, null=True,
        help_text="HTTP version used in the request. Typically HTTP/1.0 "\
                  "or HTTP/1.1.")
    http_status = models.PositiveIntegerField(
        help_text="The HTTP response code for the request.")
    error_code = models.CharField(max_length=255, blank=True, null=True,
        help_text="The Amazon S3 Error Code, or '-' if no error occurred.")
    bytes_sent = models.PositiveIntegerField(blank=True, null=True,
        help_text="The number of response bytes sent, excluding HTTP "\
                  "protocol overhead, or '-' if zero.")
    object_size = models.PositiveIntegerField(blank=True, null=True,
        help_text="The total size of the object in question.")
    total_time = models.PositiveIntegerField(blank=True, null=True,
        help_text="The number of milliseconds the request was in flight "\
                  "from the server's perspective. This value is measured "\
                  "from the time your request is received to the time that "\
                  "the last byte of the response is sent. Measurements made "\
                  "from the client's perspective might be longer due to "\
                  "network latency.")
    turnaround_time = models.PositiveIntegerField(blank=True, null=True,
        help_text="The number of milliseconds that Amazon S3 spent "\
                  "processing your request. This value is measured from "\
                  "the time the last byte of your request was received until "\
                  "the time the first byte of the response was sent.")
    referrer = models.TextField(blank=True, null=True,
        help_text="The value of the HTTP Referrer header, if present. "\
                  "HTTP user-agents (e.g. browsers) typically set this "\
                  "header to the URL of the linking or embedding page when "\
                  "making a request.")
    user_agent = models.TextField(blank=True, null=True,
        help_text="The value of the HTTP User-Agent header.")
    version_id = models.CharField(max_length=255, blank=True, null=True,
        help_text="The version ID in the request, or '-' if the operation "\
                  "does not take a versionId parameter.")

    # The following fields (by string name) have dash values replaced with
    # None values so we don't have to query by '-'.
    DASHED_TO_NONE_FIELDS = [
        'requester',
        'error_code',
        'referrer',
        'object_size',
        'version_id',
        'user_agent',
        'turnaround_time',
        'object_size',
        'bytes_sent',
        'total_time',
        'user_agent',
    ]

    def __unicode__(self):
        return "S3LogRecord: %s" % self.id

    def save(self):
        """
        Look through the dash-to-empty fields, replace dashes with a 
        None value to promote less silly query filters.
        """
        for field in self.DASHED_TO_NONE_FIELDS:
            field_val = getattr(self, field)
            if field_val == '-' or field_val == '':
                setattr(self, field, None)

        super(S3LogRecord, self).save()
