import sys

import plumper.wn.pwn as pwn
from plumper.sumo import sumo as sumo


class PWN2SUMOMapper:
	'''
	Maps the PWNSenseIndex to SumoInstance
	'''
	def __init__(self, pwn_sense_index, sumoinstance, s2p_rel, s2p_rel_shrtcut):
		self.pwn_sense_index = pwn_sense_index
		self.sumoinstance = sumoinstance
		self.sumo2pwn_relation = s2p_rel
		self.sumo2pwn_relation_shortcut = s2p_rel_shrtcut

class PWN2SUMOReader:
	'''
	Helper class for read all types of WordNetMapping30 files
	'''

	def __init__(self, filename, pwns_indexes):
		'''
		filename - name of file with map PWN -> SUMO
		pwns_indexes - dictionary of pwn index instances
		(lemma-lex_filename-senseid-pos_int_disamb) ->
		'''
		self.filename = filename
		self.pwns_indexes = pwns_indexes
	
	def read(self, clear_synset_lemma = False):
		'''
		Read mapped PWN to SUMO in given filename

		@clear_synset_lemma - Helper argument to try to clear lemma of PWN synset. 
		                      Sometimes in mapping PWN-SUMP pwn lemma have assigned 
		                      POS from badly parsing index file. If this argument 
		                      is set to True, then the module try to repair this lemma.

		Returns list of objects of PWN2SUMOMapper
		'''
		pwn2sumo = []
		with open(self.filename, 'rt') as fin:
			for line in fin:
				p2ss = self.parse_line(line, clear_synset_lemma)
				if p2ss:
					pwn2sumo.extend(p2ss)
		return pwn2sumo

	def parse_line(self, line, clear_synset_lemma):
		'''
		WARNING! Sometimes in file WordNetMappings30-adj.txt
		POS is tagged as 'a' but sometimes as 's'. Becouse in
		PWN3.0 adj dictionary, adj always is tagged as 'a', here
		all adj tagged as 's' are changed to 'a' (if necessary).

		Exemplary line:
		00434597 00 s 01 solid 0 001 & 00433115 a 0000 |
		impenetrable for the eye; "solid blackness" &%capability+

		Return list of instaces of PWN2SUMOMapper or None if given 
		line to parse is not correct. 
		Return None if line is comment (starts with semicolon ';')

		Mapping format is as follow:
		synset_offset  lex_filename  pos_as_character  ???  lemma | examples | &%SUMO_conceptRELATION_SHORTCUT

			agon%1:04:00:: 00035697 1 0 
			00035697 04 n 01 agon 0 005 (...)
		
			reparation%1:04:00:: 00095329 4 0
			00095329 04 n 02 reparation 0 amends 0 003 (...)

			break%1:04:02:: 00294748 14 0
			00294748 04 n 01 break 2 002 (...)
		
			hard%4:02:01:: 00091534 10 0
			00091534 02 r 01 hard 1 000 (...)

		Temporarly is build PWNSenseIndex _only_ for build sensekey and cheks into i
		available senses from sense.index file (PWN) To the mapping is used the sense,
		witch exists into dictionary. Temporary build sense is deleted.
		'''
		if line.startswith(';'):
			return None

		try:
			line = line.strip()
			spl_line = line.split('&%')
			if len(spl_line) == 1:
				return None
		
			p2s = []
			concept_names = spl_line[1 : ]
			split_wn_line = spl_line[0].split(' ')
			
			# build temporary PWNSenseIndex
			synset_offset = split_wn_line[0]
			lex_filename = split_wn_line[1]
			pos_as_str = split_wn_line[2]
			wn_lemma = (split_wn_line[4].split('(')[0] if clear_synset_lemma else split_wn_line[4])
			tmp_pwidx = pwn.PWNSenseIndex(wn_lemma, -1, lex_filename, synset_offset)
			tmp_pwidx.pos_int_disamb = tmp_pwidx.pos_disamb_int(pos_as_str)

			if self.pwns_indexes.has_key(tmp_pwidx.sensekey()):
				for sumo_concept_name in concept_names:
					if len(sumo_concept_name.strip()) == 0:
						continue
					# parse concept name 
					s_conc_name, s2p_rel, s2p_rel_shtcut = \
							self.get_concname_s2prel(sumo_concept_name)
					# add PWN2SUMOMapper to list of all...
					p2s.append(
							PWN2SUMOMapper(
								self.pwns_indexes[tmp_pwidx.sensekey()],
								sumo.SumoInstance(s_conc_name),
								s2p_rel,
								s2p_rel_shtcut
							)
					)
				return p2s
			else:
				print >> sys.stderr, 50 * '*'
				print >> sys.stderr, line
				print >> sys.stderr, 'Brak w slowniku', tmp_pwidx.sensekey()
		except Exception, e:
			print >> sys.stderr, 'Line: %s' % line
			print >> sys.stderr, 'Error:', e
			print >> sys.stderr, 50 * '*'
			return None
	
	def get_concname_s2prel(self, sumoconc_name):
		'''
		Parse given SUMO String (f.e. &%familyRelation=)

		Rturns triple: 
			(SUMO_concept_name, sumo2pwn_relation, sumo2pwn_relation_shortcut)
		
		Shortcuts and whole names:
			--  = equivalent  ( also : )
			--  + subsumed    ( also [ )
			--  @ instance_of ( also ] )
		'''
		sumoconc_name = sumoconc_name.strip()
		s2p_rel_name = None
		s2p_rel_shrtcut = sumoconc_name[-1]
		s_concept_name = sumoconc_name[0 : -1]
		if s2p_rel_shrtcut == '=':
			s2p_rel_name = 'equivalent'
		elif s2p_rel_shrtcut == ':':
			s2p_rel_name = 'equivalent'
		elif s2p_rel_shrtcut == '+':
			s2p_rel_name = 'subsumed'
		elif s2p_rel_shrtcut == '[':
			s2p_rel_name = 'subsumed'
		elif s2p_rel_shrtcut == '@':
			s2p_rel_name = 'instance_of'
		elif s2p_rel_shrtcut == ']':
			s2p_rel_name = 'instance_of'
		return (s_concept_name, s2p_rel_name, s2p_rel_shrtcut)

	def __make_pos_disamb(self, pos_int):
		adj_a = [0, 1, 44]
		adv = [2]
		noun = [x for x in range(3, 29)]
		verb = [x for x in range(29, 44)]

		if pos_int in adj_a:
			return 3
		elif pos_int in adv:
			return 4
		elif pos_int in noun:
			return 1
		elif pos_int in verb:
			return 2
		else:
			return 0
