# -*- coding: utf-8 -*-

import collections
import os
from lxml import etree
from io import StringIO
from cltk.stem.lemma import LemmaReplacer


class PreprocessingText(object):
	"""Used to clean strings for further processing
	"""

	def __init__(self, text):
		self.text = text

	def tokenize(self):
		"""Returns list of word tokens
		"""
		return (self.text).split()

	def clean_text(self):
		"""Cleans strings of punctuation and numbers
		"""
		clean_text = ''
		bad_punc = '1234567890!@#$%^&*()-_=+[{]}\'|\;:"<,>.?/'
		for char in str(self.text):
			if char not in bad_punc:
				clean_text += char.lower()
			else:
				pass
		return clean_text

	def clean_lewis_entry(self):
		"""Converts raw L&S entries into a standard form.
		E.g., a^bu_tor => abūtor
		"""

		raw_conversion = {'u': 'ū', 'e': 'ē', 'i': 'ī', 'o': 'ō', 'a': 'ā'}
		clean_entry = ''
		under_list = (self.text).split('_')
		for char in under_list:
			if under_list.index(char) != (len(under_list) - 1):
				long_vowel = raw_conversion.get(char[-1])
				clean_entry += (char[:-1] + long_vowel)
			else:
				clean_entry += char
		else:
			pass
		return clean_entry.replace('^', '')



class MorphInfoWord(PreprocessingText):
	"""Returns relevant morphological information at the singular word level.
	"""

	def __init__(self, word):
		self.word = word

	def lemmatize_word(self):
		"""Returns clean lemma for word.
		"""
		lemmatizer = LemmaReplacer('latin') # Intializes CLTK lemmatizer for Latin
		return PreprocessingText(lemmatizer.lemmatize(self.word)).clean_text()

	def lewis_entry_word(self):
		"""Returns clean L&S entry for word (essentially the macronized lemma)
		"""

		old_path = os.path.expanduser('~/cltk_data/latin/lexicon/latin_lexica_perseus/latin_english_lexicon_old.xml')
		with open(old_path) as f:
			old_xml = f.read()
			tree = etree.parse(StringIO(old_xml))
		entries = tree.xpath('/TEI.2/text/body/div0/entryFree')
		for entry in entries:
			key = PreprocessingText(entry.get('key'))
			if key.clean_text() == self.lemmatize_word():
				return PreprocessingText(entry.get('key')).clean_lewis_entry()
			else:
				pass


class MorphInfoText(PreprocessingText):
	"""Returns morphological information for a text
	"""

	def __init__(self, text):
		PreprocessingText.__init__(self, text) # Recieves text from Preprocessing class

	def word_list(self):
		"""Returns a dictionary with the enumerated token list as the keys and empty lists as values.
		"""
		word_list = list(enumerate(self.tokenize())) # enumerates token list
		dic_list = {k: [] for k in word_list} # creates dictionary with empty list for values
		return dic_list

	def ordered_word_list(self):
		"""Returns an ordered word list
		"""
		unordered_list = self._word_list()
		return collections.OrderedDict(sorted(unordered_list.items())) # utilizes collections library to sort


	def lemmatize_text(self):
		"""Returns a list of lemmata 
		"""
		for word in self.tokenize():
			return self.tokenize()
			return MorphInfoWord(word).lemmatize_word()

	def lewis_entry_text(self):
		"""Should returns a list of L&S entries, but the runtime is too long. When you quit the 
		process during the runtime, the terminal shows the function searching the lemmata.py dict.
		Not sure why it does this since the lemmatize_text method has no problem returning lemmata.
		"""
		
		for word in self.tokenize():
			return MorphInfoWord(str(word)).lewis_entry_word()

if __name__ == '__main__':
	SAMPLE_TEXT = 'quo usque tandem abutere catilina nostra patientia'
	SAMPLE_WORD = 'abutere'
	SAMPLE_ENTRY = 'a^bu_tor'
	print(MorphInfoText(SAMPLE_TEXT).lemmatize_text())
