# -*- coding: utf-8 -*-
"""Models for devices, heartbeats, crashreports and log files."""

import uuid

from django.db import models, transaction
from django.contrib.auth.models import User
from taggit.managers import TaggableManager


class Device(models.Model):
    """A device representing a phone that has been registered on Hiccup."""

    def __str__(self):
        """Return the UUID as string representation of a device."""
        return self.uuid

    # for every device there is a django user
    uuid = models.CharField(
        db_index=True,
        max_length=64,
        unique=True,
        default=uuid.uuid4,
        editable=False,
    )
    user = models.OneToOneField(
        User,
        related_name="Hiccup_Device",
        on_delete=models.CASCADE,
        unique=True,
    )
    imei = models.CharField(max_length=32, null=True, blank=True)
    board_date = models.DateTimeField(null=True, blank=True)
    chipset = models.CharField(max_length=200, null=True, blank=True)
    tags = TaggableManager(blank=True)
    last_heartbeat = models.DateTimeField(null=True, blank=True)
    token = models.CharField(max_length=200, null=True, blank=True)
    next_per_crashreport_key = models.PositiveIntegerField(default=1)
    next_per_heartbeat_key = models.PositiveIntegerField(default=1)

    @transaction.atomic
    def get_crashreport_key(self):
        """Get the next key for a crashreport and update the ID-counter."""
        ret = self.next_per_crashreport_key
        self.next_per_crashreport_key = self.next_per_crashreport_key + 1
        self.save()
        return ret

    @transaction.atomic
    def get_heartbeat_key(self):
        """Get the next key for a heartbeat and update the ID-counter."""
        ret = self.next_per_heartbeat_key
        self.next_per_heartbeat_key = self.next_per_heartbeat_key + 1
        self.save()
        return ret


def crashreport_file_name(instance, filename):
    """Generate the full path for new uploaded log files.

    Args:
        instance: The log file instance.
        filename: The name of the actual log file.

    Returns: The generated path including the file name.

    """
    return "/".join(
        [
            "crashreport_uploads",
            instance.crashreport.device.uuid,
            str(instance.crashreport.id),
            str(instance.crashreport.date),
            filename,
        ]
    )


class Crashreport(models.Model):
    """A crashreport that was sent by a device."""

    BOOT_REASON_UNKOWN = "UNKNOWN"
    BOOT_REASON_KEYBOARD_POWER_ON = "keyboard power on"
    BOOT_REASON_RTC_ALARM = "RTC alarm"
    CRASH_BOOT_REASONS = [BOOT_REASON_UNKOWN, BOOT_REASON_KEYBOARD_POWER_ON]
    SMPL_BOOT_REASONS = [BOOT_REASON_RTC_ALARM]

    device = models.ForeignKey(
        Device,
        db_index=True,
        related_name="crashreports",
        on_delete=models.CASCADE,
    )
    is_fake_report = models.BooleanField(default=False)
    app_version = models.IntegerField()
    uptime = models.CharField(max_length=200)
    build_fingerprint = models.CharField(db_index=True, max_length=200)
    radio_version = models.CharField(db_index=True, max_length=200, null=True)
    boot_reason = models.CharField(db_index=True, max_length=200)
    power_on_reason = models.CharField(db_index=True, max_length=200)
    power_off_reason = models.CharField(db_index=True, max_length=200)
    date = models.DateTimeField(db_index=True)
    tags = TaggableManager(blank=True)
    device_local_id = models.PositiveIntegerField(blank=True)
    next_logfile_key = models.PositiveIntegerField(default=1)
    created_at = models.DateTimeField(auto_now_add=True)

    @transaction.atomic
    def get_logfile_key(self):
        """Get the next key for a log file and update the ID-counter."""
        ret = self.next_logfile_key
        self.next_logfile_key = self.next_logfile_key + 1
        self.save()
        return ret

    def save(self, *args, **kwargs):
        """Save the crashreport and set its local ID if it was not set."""
        if not self.device_local_id:
            self.device_local_id = self.device.get_crashreport_key()
        super(Crashreport, self).save(*args, **kwargs)

    def _get_uuid(self):
        """Return the device UUID."""
        return self.device.uuid

    uuid = property(_get_uuid)


class LogFile(models.Model):
    """A log file that was sent along with a crashreport."""

    logfile_type = models.TextField(max_length=36, default="last_kmsg")
    crashreport = models.ForeignKey(
        Crashreport, related_name="logfiles", on_delete=models.CASCADE
    )
    logfile = models.FileField(upload_to=crashreport_file_name, max_length=500)
    crashreport_local_id = models.PositiveIntegerField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def save(self, *args, **kwargs):
        """Save the log file and set its local ID if it was not set."""
        if not self.crashreport_local_id:
            self.crashreport_local_id = self.crashreport.get_logfile_key()
        super(LogFile, self).save(*args, **kwargs)


class HeartBeat(models.Model):
    """A heartbeat that was sent by a device."""

    device = models.ForeignKey(
        Device,
        db_index=True,
        related_name="heartbeats",
        on_delete=models.CASCADE,
    )
    app_version = models.IntegerField()
    uptime = models.CharField(max_length=200)
    build_fingerprint = models.CharField(db_index=True, max_length=200)
    radio_version = models.CharField(db_index=True, max_length=200, null=True)
    date = models.DateTimeField(db_index=True)
    device_local_id = models.PositiveIntegerField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def save(self, *args, **kwargs):
        """Save the heartbeat and set its local ID if it was not set."""
        if not self.device_local_id:
            self.device_local_id = self.device.get_heartbeat_key()
        super(HeartBeat, self).save(*args, **kwargs)

    def _get_uuid(self):
        """Return the device UUID."""
        return self.device.uuid

    uuid = property(_get_uuid)
