from django.db import models #this import models as data type
from django.contrib.auth.models import User #use User to borrow BookInstance
from datetime import date #use to access date and time in django

'''
	everytime we change in models.py we need to call
		py -3 manage.py makemigrations
		py -3 manage.py migrate
'''
# Create your models here.
class Genre(models.Model):
	#Model representing book genre(e.g. fiction or non fiction)
	
	name = models.CharField(max_length=200, help_text="Enter a book genre(e.g. fiction or non-fiction)")
	
	def __str__(self):
		#method representing model object(in Admin site)
		return self.name


#used to generate Urls by reversing the Url patterns
from django.core.urlresolvers import reverse

class Book(models.Model):
	title = models.CharField(max_length=200)
	author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True)
	# Foreign Key used because book can only have one author, but authors can have multiple books
	# Author as a string rather than object because it hasn't been declared yet in the file.
	summary = models.TextField(max_length=1000, help_text="Enter a brief description of the book")
	isbn = models.CharField('ISBN',max_length=13, help_text='13 Character <a href="https://www.isbn-international.org/content/what-isbn">ISBN number</a>')
	genre = models.ManyToManyField(Genre, help_text="Select a genre for this book")
	# ManyToManyField used because genre can contain many books. Books can cover many genres.
	# Genre class has already been defined so we can specify the object above.
	
	def __str__(self):
			"""
			String for representing the Model object.
			"""
			return self.title
	
	def get_absolute_url(self):
			"""
			Returns the url to access a particular book instance.
			"""
			return reverse('book-detail', args=[str(self.id)])

	def display_genre(self):
		"""
		create a string for the genre to display in admin page
		"""
		return ', '.join([genre.name for genre in self.genre.all()[:3]])
	
	display_genre.short_description = "Genres"
	
	class Meta:
		ordering = ['isbn']
	
# Required for unique book instances
import uuid
class BookInstance(models.Model):
	"""
	Model representing a specific copy of a book (i.e. that can be borrowed from the library).
	"""
	id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text="Unique ID for this particular book across whole library")
	book = models.ForeignKey('Book', on_delete=models.SET_NULL, null=True) 
	imprint = models.CharField(max_length=200)
	due_back = models.DateField(null=True, blank=True)
	#add borrower data
	borrower = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)

	LOAN_STATUS = (
			('d', 'Maintenance'),
			('o', 'On loan'),
			('a', 'Available'),
			('r', 'Reserved'),
	)
	status = models.CharField(max_length=1, choices=LOAN_STATUS, blank=True, default='d', help_text='Book availability')
	
	'''
	class Meta is required by Pagination object in catalog.views.py
	and to set permissions
	'''
	class Meta:
			ordering = ["due_back"]
			#Defining permissions is done in a tuple containing the permission name and permission to display
			permissions = (("can_mark_returned", "Set book as returned"),)
			#The user's permissions are accessible in template using {{ perms }}
			'''
			(test permission in templates)
			{% if perms.catalog.can_mark_returned %}
				<!-- We can mark a BookInstance as returned. -->
				<!-- Perhaps add code to link to a "book return" view here. -->
			{% endif %}
			'''
			'''
			(test permission in function view)
			from django.contrib.auth.decorators import permission_required
			@permission_required('catalog.can_mark_returned')
			@permission_required('catalog.can_edit')
			def my_view(request):
					...
			'''
			'''
			(test permission in class-based views)
			from django.contrib.auth.mixins import PermissionRequiredMixin
			class MyView(PermissionRequiredMixin, View):
				permission_required = 'catalog.can_mark_returned'
				# Or multiple permissions
				permission_required = ('catalog.can_mark_returned', 'catalog.can_edit')
				# Note that 'catalog.can_edit' is just an example
				# the catalog application doesn't have such permission!
			'''
	
	@property
	def is_overdue(self):
		#first ensure due_back is not empty. Empty is not comparable and will throw error
		if self.due_back and date.today() > self.due_back:
			return True
		return False

	def __str__(self):
			"""
			String for representing the Model object
			"""
			return '%s (%s)' % (self.id,self.book.title)
				
class Author(models.Model):
	"""
	Model representing an author.
	"""
	first_name = models.CharField(max_length=100)
	last_name = models.CharField(max_length=100)
	date_of_birth = models.DateField(null=True, blank=True)
	date_of_death = models.DateField('Died', null=True, blank=True)
		
	def get_absolute_url(self):
			"""
			Returns the url to access a particular author instance.
			"""
			return reverse('author-detail', args=[str(self.id)])

	def __str__(self):
			"""
			String for representing the Model object.
			"""
			return '%s, %s' % (self.last_name, self.first_name)
	
	class Meta:
		ordering = ['last_name']
			
class Language(models.Model):
	"""
	Model representing a Language (e.g. English, French, Japanese, etc.)
	"""
	name = models.CharField(max_length=200, help_text="Enter a the book's natural language (e.g. English, French, Japanese etc.)")
	
	def __str__(self):
			"""
			String for representing the Model object (in Admin site etc.)
			"""
			return self.name