import os

from django.db import models
from django.contrib.auth.models import User  

class UserProfile(models.Model):
	user = models.OneToOneField(User, related_name='profile')
	url = models.URLField()

class Architecture(models.Model):
	safename = models.CharField(maxlength=15)
	name = models.CharField(maxlength=30)
#	summary = models.TextField()
	
	def status_for_kern(self, kern):
		tests = FunctionalTest.objects.filter(kversion__id=kern.id, client__arch__id=self.id)

		if tests.count() > 0:
			val = 0
			for test in tests:
				val = max(val, test.status_id)
			result = Status.objects.get(id=val)
		else:
			result = None

 		return result

	def __str__(self):
		return self.name

	class Meta:
		ordering = ['name']
	
	class Admin:
		list_display = ('safename', 'name') 

class ClientMachine(models.Model):
	owner = models.ForeignKey(User)
	arch = models.ForeignKey(Architecture, verbose_name='architecture')
	name = models.CharField(maxlength=30)
	hostname  = models.CharField(maxlength=200)  
	info_url = models.URLField(blank=True) 
	last_seen = models.DateTimeField(null=True )

	def all_archs():
		client_tbl = ClientMachine._meta.db_table # 'lkrt_clientmachine'
		arch_tbl = Architecture._meta.db_table # 'lkrt_architecture'
		return Architecture.objects.extra(tables=[client_tbl], where=['%s.arch_id=%s.id' % (client_tbl, arch_tbl)] ).distinct()
	all_archs = staticmethod(all_archs)

	def __str__(self):
		return self.hostname

	class Admin:
		list_display = ('name', 'hostname', 'arch', 'owner', 'last_seen')

class ToolchainProfile(models.Model):
	manufacturer = models.CharField(maxlength=60)
	cc_version = models.CharField(maxlength=30)
	ld_version = models.CharField(maxlength=30)

	def __str__(self):
		return self.name

	class Admin:
		list_display = ('manufacturer', 'cc_version', 'ld_version') 

class SourceTree(models.Model):
	safename = models.CharField(maxlength=30)
	name = models.CharField(maxlength=200)
	url  = models.URLField() 

	watchers = models.ManyToManyField(User, related_name='trees_watching')

	def __str__(self):
		return self.name

	class Admin:
		list_display = ('safename', 'name', 'url')

class File(models.Model):
	# is there a need for both name and url, or can name be extracted from url?
	#name = models.CharField(maxlength=20)
	url = models.URLField(unique=True)

	def get_name(self):
		return os.path.basename(self.url)
	name = property(get_name) 

	def __str__(self):
		return self.name

	class Admin:
		pass

class KernelVersion(models.Model):
	tree = models.ForeignKey(SourceTree, related_name='kernel_versions')
	base = models.CharField(maxlength=30)
	
	patches = models.ManyToManyField(File)
  	 
	def save(self):
		# try to figure out tree if it wasn't already set
 		if self.base != None and self.tree_id == None:
			if self.base.count('git') > 0:
				self.tree = SourceTree.objects.get(safename='snapshot')
			elif self.base.count('ac') > 0:
				self.tree = SourceTree.objects.get(safename='ac')
			elif self.base.count('dj') > 0:
				self.tree = SourceTree.objects.get(safename='dj')
			elif self.base.count('mm') > 0:
				self.tree = SourceTree.objects.get(safename='mm')
			elif self.base.count('rc') > 0:
				self.tree = SourceTree.objects.get(safename='pre')
			else: 
				self.tree = SourceTree.objects.get(safename='main')
		
		super(KernelVersion, self).save() 
 
	def status_for_arch(self, arch):
		tests = FunctionalTest.objects.filter(kversion__id=self.id, client__arch__id=arch.id)

		if tests.count() > 0:
			val = 0
			for test in tests:
				val = max(val, test.status_id)
			result = Status.objects.get(id=val)
		else:
			result = None

 		return result
 
	def add_patch_at_url(self, url):
		patch, created = File.objects.get_or_create(url=url)
		self.patches.add(patch)

	def get_printable(self):
		result = self.base
		for patch in self.patches.all():
			result = "%s +%s" % (result, patch.name)
		return result
	printable = property(get_printable)

	def __str__(self):
		return self.printable

	class Meta:
		ordering = ['id']

	class Admin:
		list_display = ('printable', 'tree')

class Status(models.Model):
	name = models.CharField(maxlength=15) 

	def __str__(self):
		return self.name
	
	class Meta:
		verbose_name_plural = 'statuses'

	class Admin:
		pass

# what's the difference between this and the FunctionalJob  
#class Job(models.Model):
#	tag = models.CharField(maxlength=15)
#	kversion = models.ForeignKey(KernelVersion)
#	status = models.ForeignKey(Status)
#	reason = models.CharField(maxlength=100) 
#	machine = models.ForeignKey(ClientMachine)

#	def __str__(self):
#		return self.machine, self.kversion, self.status

class TestType(models.Model):
	name = models.CharField(maxlength=30, unique=True)

	def __str__(self):
		return self.name

	class Admin:
		pass

class FunctionalTest(models.Model):
	type = models.ForeignKey(TestType)
#	subdir = models.CharField(maxlength=60)
	kversion = models.ForeignKey(KernelVersion, verbose_name='kernel version', related_name='functional_tests')
	client = models.ForeignKey(ClientMachine)
	status = models.ForeignKey(Status)
	reason = models.CharField(maxlength=1024)

	def __str__(self):
		return "%s test of %s: %s" % (self.type, self.kversion, self.status) 

	class Admin:
		list_display = ('id', 'kversion', 'client', 'type', 'status', 'reason')

#class TestAttribute(models.Model):
#	name = models.CharField(maxlength=20)
#
#	def __str__(self):
#		return self.name

#class Result(models.Model):
#	job = models.ForeignKey(Job)
#	test = models.ForeignKey(Test)
#	subdir = models.CharField(maxlength=60)
#	kversion = models.ForeignKey(KernelVersion)
#	attribute = models.ForeignKey(TestAttribute)
#  	value = models.IntegerField()

#	def __str__(self):
# 		return self.test, self.kversion

def create_initial_data():
	if  Status.objects.count() > 0:
		return
	
	Status ( name='GOOD' ).save()
	Status ( name='WARN' ).save()
	Status ( name='FAIL' ).save()
	Status ( name='ABORT' ).save()

	Architecture(	safename='alpha', name='Alpha' ).save()
	Architecture(	safename='arm', name='ARM' ).save()
	Architecture(	safename='arm26', name='ARM26' ).save()
	Architecture(	safename='cris', name='CRIS' ).save()
	Architecture(	safename='frv', name='FRV' ).save()
	Architecture(	safename='h8300', name='H8300 ' ).save()
	Architecture(	safename='i386', name='i386' ).save()
	Architecture(	safename='ia64', name='IA-64' ).save()
	Architecture(	safename='m32r', name='M32R' ).save()
	Architecture(	safename='m68k', name='m68k' ).save()
	Architecture(	safename='m68knommu', name='m68knommu' ).save()
	Architecture(	safename='mips', name='MIPS' ).save()
	Architecture(	safename='parisc', name='PA-RISC' ).save()
	Architecture(	safename='powerpc', name='PowerPC' ).save()
	Architecture(	safename='s390', name='s390' ).save()
	Architecture(	safename='sh', name='SH' ).save()
	Architecture(	safename='sh64', name='SH64' ).save()
	Architecture(	safename='sparc', name='SPARC' ).save()
	Architecture(	safename='sparc64', name='SPARC-64' ).save()
	Architecture(	safename='um', name='User Mode Linux' ).save()
	Architecture(	safename='v850', name='v850' ).save()
	Architecture(	safename='x86_64', name='x86_64' ).save()
	Architecture(	safename='xtensa', name='Xtensa' ).save()

	SourceTree( safename='main', name='main line',  url='http://kernel.org' ).save()
	SourceTree( safename='ac', name="-ac patch line" , url='http://kernel.org/patchtypes/ac.html' ).save() 
	SourceTree( safename='dj', name="-dj patch line", url='http://kernel.org/patchtypes/dj.html' ).save() 
	SourceTree( safename='mm', name="-mm patch line", url='http://kernel.org/patchtypes/mm.html' ).save()
	SourceTree( safename='pre', name='prepatch', url='http://kernel.org/patchtypes/pre.html'  ).save() 
	SourceTree( safename='snapshot', name='snapshot', url='http://kernel.org/patchtypes/pre.html'  ).save() 

	tobias = User.objects.get(username='tobias')

	x86_64 = Architecture.objects.get(safename='x86_64')
	ppc = Architecture.objects.get(safename='powerpc')
	x86 = Architecture.objects.get(safename='i386') 
 
	ClientMachine( name='elm3b6', owner=tobias, arch=x86_64, hostname='elm3b6').save()  
	ClientMachine( name='moe', owner=tobias, arch=x86, hostname='moe').save()   
	ClientMachine( name='elm3b132', owner=tobias, arch=x86, hostname='elm3b132').save()   
	ClientMachine( name='elm3b133', owner=tobias, arch=x86, hostname='elm3b133').save()   
	ClientMachine( name='gekko-lp1', owner=tobias, arch=ppc, hostname='gekko-lp1').save()  
	ClientMachine( name='pSeries-101', owner=tobias, arch=ppc , hostname='pSeries-101').save()   
	ClientMachine( name='bl6-13', owner=tobias, arch=x86_64, hostname='bl6-13').save()  
	ClientMachine( name='elm3b239', owner=tobias, arch=x86_64, hostname='elm3b239').save()  


