class PWNSenseIndex:
	'''
	This class represents one index from sensefile index
	'''

	# def __init__(self, lemma, pos_int, sensenum, senseid):
	def __init__(self, lemma, ss_type, lex_filename, synset_offset):
		self.lemma = lemma
		self.pos_int = int(ss_type)
		self.lex_filename = lex_filename
		self.synset_offset = synset_offset

		# disambiguated POS - disambiguation between sense.index and mapping
		# this field is set manually by the user, where:
		#   - 1 Noun
		#   - 2 Verb
		#   - 3 Adjective, Adjective satellite
		#   - 4 Adverb
		self.pos_int_disamb = None
		self.lex_id = None
		self.sensenum = None
		self.head_word = None
		self.head_id = None
		self.tag_cnt = None
	
	'''
	def pos_str(self):
		' ''
		Return pos as string
		' ''
		adj_a = [0, 1, 44]
		# adj_s = []
		adv = [2]
		noun = [x for x in range(3, 29)]
		verb = [x for x in range(29, 44)]
		if self.pos_int in adj_a:
			return 'a'
		# else if self.pos_int in adj_s:
		# 	return 's'
		elif self.pos_int in noun:
			return 'n'
		elif self.pos_int in verb:
			return 'v'
		elif self.pos_int in adv:
			return 'r'
	'''

	def pos_disamb_str(self):
		'''
		Return disambiguated pos as string
		'''
		if self.pos_int_disamb == 1:
			return 'n'
		elif self.pos_int_disamb == 2:
			return 'v'
		elif self.pos_int_disamb == 3:
			return 'a'
		elif self.pos_int_disamb == 4:
			return 'r'
		
	def pos_disamb_int(self, pos_as_str):
		'''
		Return disambiguated pos as integer
		'''
		if pos_as_str == 'n':
			return 1
		elif pos_as_str == 'v':
			return 2
		elif pos_as_str == 'a' or pos_as_str == 's':
			return 3
		elif pos_as_str == 'r':
			return 4
		return 0

	def make_based_on_str(self, sensestr):
		'''
		Based on given sense string makes new PWNSenseIndex. 
		Exemplary string: baudelaire%1:18:00:: 10838484 1 0

		Return new object of PWNSenseIndex class made based on given 
		string or None if given string is not correct
		Return None if line is comment (starts with semicolon ';')

		Format of sense.index is as follow:
			sense_key  synset_offset  sense_number  tag_cnt
		Where sense_key is: lemma % lex_sense
		Where lex_sense is: ss_type:lex_filenum:lex_id:head_word:head_id
		ss_type = {
			1 NOUN,
			2 VERB ,
			3 ADJECTIVE ,
			4 ADVERB,
			5 ADJECTIVE SATELLITE}

		For example: acicular%5:00:00:simple:01 02167133 1 0

		sense_key = acicular%5:00:00:simple:01
			lemma = acicular
			lex_sense = 5:00:00:simple:01
				ss_type = 5 (Adj sat)
				lex_filename = 00
				lex_id = 00
				head_word = simple
				head_id = 01
		synset_offset = 02167133
		sense_number = 1
		tag_cnt = 0

		Full description of sense.index is available on 
		http://wordnet.princeton.edu/man/senseidx.5WN.html
		'''
		if sensestr.startswith(';'):
			return None
		try:
			sense_key, synset_offset, sense_number, tag_cnt = sensestr.strip().split(' ')
			lemma, lex_sense = sense_key.split('%')
			ss_type, lex_filename, lex_id, head_word, head_id = lex_sense.split(':')

			sindex = PWNSenseIndex(lemma, ss_type, lex_filename, synset_offset)
			sindex.lex_id = lex_id
			sindex.sensenum = int(sense_number)
			sindex.head_word = head_word
			sindex.head_id = head_id
			sindex.tag_cnt = tag_cnt
			sindex.__make_disamb_pos()
			return sindex
		except Exception, e:
			return None

	def sensekey(self):
		return '%s:%s:%d:%s' % (
				self.lemma.lower(), 
				self.lex_filename, 
				self.pos_int_disamb,
				self.synset_offset)

	def __make_disamb_pos(self):
		# n
		if self.pos_int == 1:
			self.pos_int_disamb = 1
		# v
		elif self.pos_int == 2:
			self.pos_int_disamb = 2
		# adj
		elif self.pos_int == 3 or self.pos_int == 5:
			self.pos_int_disamb = 3
		# adv
		elif self.pos_int == 4:
			self.pos_int_disamb = 4
		else:
			self.pos_int_disamb = 0

class PWNSenseIndexReader:
	'''
	Reader for sense.index file
	'''

	def __init__(self, indexpath):
		self.indexpath = indexpath
		#helper temporary sense
		self.__tmp_sense = PWNSenseIndex('tmp', -1, -1, -1)

	def read(self):
		'''
		Read sense index file and makes list of possible PWNSenseIndex objects

		Return list of PWNSenseIndex
		'''
		senses = dict()
		with open(self.indexpath, 'rt') as fin:
			for line in fin:
				sense = self.parse_line(line)
				if sense:
					key = sense.sensekey()
					senses[key] = sense
		return senses

	def parse_line(self, senseline):
		'''
		Parse sense line, such as:
		baudelaire%1:18:00:: 10838484 1 0

		For parse uses temporary PWNSenseIndex object
		'''
		return self.__tmp_sense.make_based_on_str(senseline)

