from django.db import models
from django.contrib.auth import get_user_model
import uuid

from uncloud_pay.models import Product, RecurringPeriod
import uncloud_pay.models as pay_models


class VMHost(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    # 253 is the maximum DNS name length
    hostname = models.CharField(max_length=253, unique=True)

    # indirectly gives a maximum number of cores / VM - f.i. 32
    physical_cores = models.IntegerField(default=0)

    # determines the maximum usable cores - f.i. 320 if you overbook by a factor of 10
    usable_cores = models.IntegerField(default=0)

    # ram that can be used of the server
    usable_ram_in_gb = models.FloatField(default=0)


    status = models.CharField(max_length=32,
                              choices = (
                                  ('pending', 'Pending'),
                                  ('active', 'Active'),
                                  ('unusable', 'Unusable'),
                                  ('deleted', 'Deleted'),
                              ),
                              default='pending'
    )


class VMProduct(Product):
    vmhost   = models.ForeignKey(VMHost,
                                 on_delete=models.CASCADE,
                                 editable=False,
                                 blank=True,
                                 null=True)

    description = "Virtual Machine"
    cores = models.IntegerField()
    ram_in_gb = models.FloatField()

    def recurring_price(self, recurring_period=RecurringPeriod.PER_MONTH):
        if recurring_period == RecurringPeriod.PER_MONTH:
            # TODO: move magic numbers in variables
            return self.cores * 3 + self.ram_in_gb * 2
        else:
            raise Exception('Invalid recurring period for VM Product pricing.')


class VMWithOSProduct(VMProduct):
    pass

class VMDiskProduct(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    vm   = models.ForeignKey(VMProduct, on_delete=models.CASCADE)
    size_in_gb = models.FloatField()

    storage_class = models.CharField(max_length=32,
                              choices = (
                                  ('hdd', 'HDD'),
                                  ('ssd', 'SSD'),
                              ),
                              default='ssd'
    )

class OperatingSystemDisk(VMDiskProduct):
    """ Defines an Operating System Disk that can be cloned for a VM """
    os_name = models.CharField(max_length=128)


class VMNetworkCard(models.Model):
    vm   = models.ForeignKey(VMProduct, on_delete=models.CASCADE)

    mac_address = models.IntegerField()

    ip_address = models.GenericIPAddressField(blank=True,
                                              null=True)


class VMSnapshotProduct(Product):
    price_per_gb_ssd = 0.35
    price_per_gb_hdd = 1.5/100

    # This we need to get from the VM
    gb_ssd = models.FloatField(editable=False)
    gb_hdd = models.FloatField(editable=False)

    vm = models.ForeignKey(VMProduct, on_delete=models.CASCADE)
    #vm_uuid = models.UUIDField()

    # Need to setup recurring_price and one_time_price and recurring period

    sample_ssd = 10
    sample_hdd = 100

    def recurring_price(self):
        return 0

    def one_time_price(self):
        return 0

    @classmethod
    def sample_price(cls):
        return cls.sample_ssd * cls.price_per_gb_ssd + cls.sample_hdd * cls.price_per_gb_hdd

    description = "Create snapshot of a VM"
    recurring_period = "monthly"

    @classmethod
    def pricing_model(cls):
        return """
Pricing is on monthly basis and storage prices are equivalent to the storage
price in the VM.

Price per GB SSD is: {}
Price per GB HDD is: {}


Sample price for a VM with {} GB SSD and {} GB HDD VM is: {}.
""".format(cls.price_per_gb_ssd, cls.price_per_gb_hdd,
           cls.sample_ssd, cls.sample_hdd, cls.sample_price())