from django.db import models
from datetime import date, timedelta
from tinymce.models import HTMLField


PERIMETER_CHOICES = (
    ('Internal', 'Internal'),
    ('External', 'External'),
)

RISK_CHOICES = (
    ('Critical', 'Critical'),
    ('High', 'High'),
    ('Medium', 'Medium'),
    ('Low', 'Low'),
    ('Not evaluated', 'Not evaluated')
)

STATUS_CHOICES = (
    ('Solved', 'Solved'),
    ('Notified', 'Notified'),
    ('Accepted', 'Accepted'),
    ('Mitigated', 'Mitigated'),
    ('Not identified', 'Not identified'),
)

class Vulnerability(models.Model):
    #### Vulnerability fields:
    system = models.CharField(max_length=256, blank=False, \
        help_text="(Required) The system presenting the vulnerability.")
    system_type = models.CharField(max_length=256, blank=False, \
        help_text="(Required) Ex: WEB application, Windows Server, Linux Server, Mobilie application, etc.")
    technology = models.CharField(max_length=256, blank=False, \
        help_text="(Required) Ex: ASP.NET, Joomla, PHP, Java, Apache, etc.")
    environment = models.CharField(max_length=64, blank=False, \
        help_text="(Required) Ex: Datacenter, Local server, Cloud, etc.")
    perimeter = models.CharField(max_length=8, blank=False, \
        default='Unspecified', choices=PERIMETER_CHOICES, \
        help_text="(Required) The target system's most accessible surface.")
    owner = models.CharField(max_length=256, blank=False, \
        help_text="(Required) The target system's owner/responsible.")
    owner_email = models.EmailField(max_length=64, blank=False, \
        help_text="(Required) The owner's email address.")
    vulnerability = models.CharField(max_length=512, blank=False, \
        help_text="(Required) The vulnerability name, as reported by the researchers.")
    synopsis = HTMLField(max_length=10485760, default='Not provided', blank=False, \
        help_text="(Required) A short description of the vulnerability. Hint: try to focus in the risks associated with the vulnerability.")
    category = models.CharField(max_length=512, blank=True, default='Unknown', \
        help_text="(Optional) For instance, refer to <a target='_blank' href='https://www.owasp.org/index.php/Category:Vulnerability'>OWASP</a> for examples of some categories. But, feel free to set your own.")
    identification_date = models.DateField(blank=False, \
        help_text="(Required) When vulnerability was discovered/reported." )
    remediation_deadline = models.DateField(blank=False, \
        help_text="(Required) A feasible deadline to fix the vulnerability.")
    remediation = HTMLField(max_length=10485760, blank=True, default='Not provided', \
        help_text="(Optional) The remediation intented to fix the vulnerability.")
    status = models.CharField(max_length=16, blank=False, choices=STATUS_CHOICES, \
        help_text="(Required)")
    observation = HTMLField(max_length=10485760, blank=True, default='Not provided', \
        help_text="(Optional) Any observation pointed by the researcher when comment this vulnerability.")
    risk = models.CharField(default="Not evaluated", blank=False, max_length=10485760, choices=RISK_CHOICES, \
        help_text="(Required)")
    risk_vector = models.CharField(default='Not evaluated', blank=True, max_length=64, \
        help_text="(Optional) The risk vector as indicated by Risk calculator.")
    risk_acceptance_reason = models.CharField(max_length=4096, blank=True, default='Not provided', \
        help_text="(Optional) Important if you decide to accept the associated risks.")
    cvss_value = models.FloatField(blank=False, \
        help_text="(Required)")
    cvss_vector = models.CharField(default='Not evaluated', blank=True, max_length=64, \
        help_text="(Optional) The CVSS 3.0 Vector string.")
    reporter = models.CharField(max_length=64, default='Not provided', blank=True, \
        help_text="(Optional) The company, research team or pentester which found the vulnerability.")
    report_file = models.CharField(max_length=256, default='Not provided', blank=True, \
        help_text="(Optional) The report file for further reference.")
    report_page = models.IntegerField(default=0, blank=True, \
        help_text="(Optional) The report page number which describes the vulnerabity.")

    def remediation_time_remaining(self):
        ''' 
        Count the remaining time between the remediation deadline and now.
        Notice that, if it returns a negative number, remediation_deadline has
        passed.
        '''
        now = date.today()
        tmp = Vulnerability.objects.get(pk=self.id)
        deadline = tmp.remediation_deadline
        elapsed_time = deadline - now

        if elapsed_time < timedelta(0):
            return(timedelta(0).days)
        else:
            return (elapsed_time.days)

    class Meta:
        verbose_name_plural = 'vulnerabilities'
        permissions = (
            ('read_vulnerability', 'Can read vulnerability'),
            ('detail_vulnerability', 'Can detail vulnerability'),
            ('delete_all_vulnerability', 'Can delete all vulnerabilities'),
        )

class RiskQuestions(models.Model):
    #### Risk questions fields:
    position = models.IntegerField(unique=True, blank=False, \
        help_text="<small><span class='text-muted'>The question position number (1, 2, 3, etc...)")
    question = models.CharField(unique=True, max_length=256, blank=False, \
        help_text="<small><span class='text-muted'>The question itself.")
    question_shortname = models.CharField(unique=True, max_length=6, blank=False, \
        help_text="<small><span class='text-muted'>A short name to identify this question when create the Risk Vector.")
    weight = models.FloatField(blank=False, default=1, \
        help_text="<small><span class='text-muted'>Add a float number if you need to ponderate this question value.")

    class Meta:
        verbose_name_plural = 'risk questions'
        ordering = ['position']
