#! /usr/bin/env python2.2
#
#This file contains basic functionality to process Status files
#and assign/compare ebuild levels.
#It is imported by portage.py.
#See also Status.skel for more info
#

#Exceptions, exceptions!
class StatusError(Exception):
	"""A very basic one"""
	def __init__ (self,reason=None,message=None):
		self.reason=reason
		self.message=message


#I'll do the list of status levels. This will allow to do comparisions in an 
#extensible way - so that if there is a decision to change level stucture
#doing that will be a matter of changing few lists only.
#ATTENTION: order is important!!
eStatusList=["unstable","new","confirmed","appr-new","core-new","approved","core"]
#these are the levels as defined in make.conf etc.

#the following switches are used in Status files
eStatusSwitches=["unstable","no","yes","core"]

#the order in Status file: confirmed_flag approved_flag - 
#thus "yes no" will correspond to confirmed (and not approved) status

#this one maps unique pairs to corresponding states
#the rest (two "special cases") are processed in the code
eStatusMap={('no','no'):"new",("yes","no"):"confirmed",("no","yes"):"appr-new",
("yes","yes"):"approved",("no","core"):"core-new",("yes","core"):"core"}

#this class will process ebuild Status (single line)
class ebuildStatus:
	def __init__ (self,pkgName,mypkgVR=None,myConf=None,myAppr=None,statusStr=None):
		'''call like: eStatus(pkgName,PVR,Conf,Appr)
		or: eStatus(pkgName,statusStr=str_from_Status_file)'''
		if pkgName:self.pkgName=pkgName
		else:raise StatusError("pkgname missing")
		
		#store (PVR,conf,appr) tuple internally
		#generate Status string as necessary
		if mypkgVR and myConf and myAppr:
			self.PVR=mypkgVR
			self.confInd=eStatusSwitches.index(myConf)
			self.apprInd=eStatusSwitches.index(myAppr)
		else:self.setFromStr(statusStr)
		#check validity
		tmp=self.get()

	def get (self):
		"returns status from the eStatusList"
		#check unstable first, then use Map and then check for core
		#ATTN!! the following line relies on "unstable" being 1st in eStatusList
		if not(self.confInd and self.apprInd):return "unstable"
		ind=(eStatusSwitches[self.confInd],eStatusSwitches[self.apprInd])
		if eStatusMap.has_key(ind):return eStatusMap[ind]
		#now only 3 possible variants left: ("core","core/yes/no")
		#since "core" is not supposed to appear in confirmed fiels I'll raise an exception
		raise StatusError("unexpected 'core' in user field","override eStatusClass.get to change this behavior")
			

	def getStatusStr (self):
		"returns string suitable for Status file"
		return " ".join((self.PVR,eStatusSwitches[self.confInd],eStatusSwitches[self.apprInd]))

	def setFromStr (self,myStr):
		"initializes object from Status string"
		try:
			self.PVR,conf,appr=myStr.split()
		except:raise StatusError("problematic Status string!","insufficient number of entries!")
		try:
			self.confInd=eStatusSwitches.index(conf)
			self.apprInd=eStatusSwitches.index(appr)
		except ValueError:raise StatusError("problematic Status string!","incorrect Status entries.")
		
	def isAllowed (self,StabLevel):
		"returns true if status is greater (more stable) then specified level"
		#StabLevel:eStateList
		return eStatusList.index(StabLevel) <= eStatusList.index(self.get())
	

class pkgStatus:
	'''This will hold info on all ebuilds associated with certain package 
	This class will have properties similar to dictionary
	but can be initialized from the Status file'''

	def __init__(self,pkgDir):
		'''Reads Status file in pkgDir'''
		#find and open Status file
		self.dict={}
		if os.path.exists(pkgDir+"/Status"):
			f=file(pkgDir+"/Status")
		else:return
		try:
			
		finally:f.close()

	def __getitem__ (self,PVR):
		"returns ebuildStatus for a given VersionRevision number"
