# -*- coding: utf-8 -*-
from django.db import models
from django.db import transaction

from django.contrib.auth.models import User
from taggit.managers import TaggableManager

import uuid


class Device(models.Model):
    def __str__( self ):
        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):
        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):
        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):
    return '/'.join([
        "crashreport_uploads",
        instance.crashreport.device.uuid,
        str(instance.crashreport.id),
        str(instance.crashreport.date),
        filename])


class Crashreport(models.Model):
    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):
        ret = self.next_logfile_key
        self.next_logfile_key = self.next_logfile_key + 1
        self.save()
        return ret

    def save(self, *args, **kwargs):
        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):
        "Returns the person's full name."
        return self.device.uuid
    uuid = property(_get_uuid)

#TODO remove logfile_type or make it meaningful
class LogFile(models.Model):
    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):
        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):
    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):
        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):
        "Returns the person's full name."
        return self.device.uuid
    uuid = property(_get_uuid)
