from future_builtins import zip

import collections as _coll
import csv as _csv

import corpus2 as _c2
import desifex as _dsf
import desifex.constants as _co

_TAGSET = _c2.get_named_tagset('nkjp')

def process(input_file, task_options, output_file):
	fetcfg =  _FextorbisFeaturesConfig()

	for opt in task_options['features'].split():
		getattr(fetcfg, 'opt_' + opt)()

	fetset = _dsf.FeatureSet(fetcfg.features, _TAGSET)
	docex = _dsf.DocExtractor(fetset, _TAGSET, 'ccl')
	results = docex.extract_from_document(input_file)

	flat_results = {}

	for fet, res in results.iteritems():
		for resnam, resval in res.iteritems():
			flat_results[fet if len(res) == 1 else resnam] = resval
			# flat_results[':'.join((fet, resnam))] = resval

	with open(output_file, 'wb') as csv_ofs:
		_write_csv(flat_results, csv_ofs)

def _write_csv(dict_, outfile):
	wr = _csv.writer(outfile, delimiter=';')

	for row in zip(*dict_.iteritems()):
		wr.writerow([unicode(col).encode('utf8') for col in row])


class _FextorbisFeaturesConfig(object):

	def __init__(self):
		self.features = []
		self._args_lex_classes = None
		self._args_proper_names = None

	def opt_base(self):
		self.features.append({
				_co.CFG_FET_NAME: 'base',
				_co.CFG_FET_CLASS: 'lemmacount',
				_co.CFG_FET_SEC_ARGS: dict(
					limit_file='config/nkjp360-meaningless-no-prep-freq-above-3500.txt'
					),
				})

	def opt_orth(self):
		self.features.append({
				_co.CFG_FET_NAME: 'orth',
				_co.CFG_FET_CLASS: 'orthcount',
				_co.CFG_FET_SEC_ARGS: dict(
					limit_file='config/wordlist100.txt',
					),
				})

	def opt_interp_signs(self):
		self.features.append({
				_co.CFG_FET_NAME: 'interp',
				_co.CFG_FET_CLASS: 'interpcount',
				_co.CFG_FET_SEC_ARGS: dict(
					grouping=dict(
						fullstop='.',
						comma=',',
						semicolon=';',
						question_mark='?',
						exclamation_mark='!',
						),
					limit_to_groups=True,
					),
				})

	def opt_verb_count(self):
		self._ensure_lex_classes()
		verbs = frozenset([
				'fin',
				'bedzie',
				'aglt',
				'praet',
				'impt',
				'imps',
				'inf',
				'pcon',
				'pant',
				'ger',
				'pact',
				'ppas',
				'winien',
				])
		self._args_lex_classes['limit_list'] |= verbs
		self._args_lex_classes['grouping']['verb'] = verbs

	def opt_noun_count(self):
		self._ensure_lex_classes()
		nouns = frozenset([
				'subst',
				'depr',
				'ppron12',
				'ppron3',
				])
		self._args_lex_classes['limit_list'] |= nouns
		self._args_lex_classes['grouping']['noun'] = nouns

	def opt_all_adj_count(self):
		self._ensure_lex_classes()
		adjs = frozenset([
				'adj',
				'adja',
				'adjp',
				'adjc',
				])
		self._args_lex_classes['limit_list'] |= adjs
		self._args_lex_classes['grouping']['all_adj'] = adjs

	def opt_subst_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('subst')
		self._args_lex_classes['grouping']['subst'] = 'subst'

	def opt_depr_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('depr')
		self._args_lex_classes['grouping']['depr'] = 'depr'

	def opt_num_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('num')
		self._args_lex_classes['grouping']['num'] = 'num'

	def opt_numcol_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('numcol')
		self._args_lex_classes['grouping']['numcol'] = 'numcol'

	def opt_adj_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('adj')
		self._args_lex_classes['grouping']['adj'] = 'adj'

	def opt_adja_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('adja')
		self._args_lex_classes['grouping']['adja'] = 'adja'

	def opt_adjp_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('adjp')
		self._args_lex_classes['grouping']['adjp'] = 'adjp'

	def opt_adjc_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('adjc')
		self._args_lex_classes['grouping']['adjc'] = 'adjc'

	def opt_adv_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('adv')
		self._args_lex_classes['grouping']['adv'] = 'adv'

	def opt_ppron12_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('ppron12')
		self._args_lex_classes['grouping']['ppron12'] = 'ppron12'

	def opt_ppron3_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('ppron3')
		self._args_lex_classes['grouping']['ppron3'] = 'ppron3'

	def opt_siebie_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('siebie')
		self._args_lex_classes['grouping']['siebie'] = 'siebie'

	def opt_winien_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('winien')
		self._args_lex_classes['grouping']['winien'] = 'winien'

	def opt_pred_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('pred')
		self._args_lex_classes['grouping']['pred'] = 'pred'

	def opt_prep_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('prep')
		self._args_lex_classes['grouping']['prep'] = 'prep'

	def opt_conj_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('conj')
		self._args_lex_classes['grouping']['conj'] = 'conj'

	def opt_comp_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('comp')
		self._args_lex_classes['grouping']['comp'] = 'comp'

	def opt_interj_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('interj')
		self._args_lex_classes['grouping']['interj'] = 'interj'

	def opt_burk_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('burk')
		self._args_lex_classes['grouping']['burk'] = 'burk'

	def opt_qub_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('qub')
		self._args_lex_classes['grouping']['qub'] = 'qub'

	def opt_brev_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('brev')
		self._args_lex_classes['grouping']['brev'] = 'brev'

	def opt_fin_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('fin')
		self._args_lex_classes['grouping']['fin'] = 'fin'

	def opt_bedzie_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('bedzie')
		self._args_lex_classes['grouping']['bedzie'] = 'bedzie'

	def opt_aglt_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('aglt')
		self._args_lex_classes['grouping']['aglt'] = 'aglt'

	def opt_praet_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('praet')
		self._args_lex_classes['grouping']['praet'] = 'praet'

	def opt_impt_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('impt')
		self._args_lex_classes['grouping']['impt'] = 'impt'

	def opt_imps_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('imps')
		self._args_lex_classes['grouping']['imps'] = 'imps'

	def opt_inf_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('inf')
		self._args_lex_classes['grouping']['inf'] = 'inf'

	def opt_pcon_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('pcon')
		self._args_lex_classes['grouping']['pcon'] = 'pcon'

	def opt_pant_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('pant')
		self._args_lex_classes['grouping']['pant'] = 'pant'

	def opt_ger_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('ger')
		self._args_lex_classes['grouping']['ger'] = 'ger'

	def opt_pact_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('pact')
		self._args_lex_classes['grouping']['pact'] = 'pact'

	def opt_ppas_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('ppas')
		self._args_lex_classes['grouping']['ppas'] = 'ppas'

	def opt_interp_count(self):
		self._ensure_lex_classes()
		self._args_lex_classes['limit_list'].add('interp')

	def opt_person_last_nam(self):
		self._ensure_proper_names()
		self._args_proper_names['grouping']['surnames'] = ['person_last_nam']

	def opt_person_first_nam(self):
		self._ensure_proper_names()
		self._args_proper_names['grouping']['first_names'] = ['person_first_nam']

	def opt_city_nam(self):
		self._ensure_proper_names()
		self._args_proper_names['grouping']['city_names'] = ['city_nam']

	def opt_country_nam(self):
		self._ensure_proper_names()
		self._args_proper_names['grouping']['country_names'] = ['country_nam']

	def opt_road_nam(self):
		self._ensure_proper_names()
		self._args_proper_names['grouping']['road_names'] = ['road_nam']

	def opt_verb12(self):
		self.features.append({
				_co.CFG_FET_NAME: 'verb12',
				_co.CFG_FET_CLASS: 'multilexclasscount',
				_co.CFG_FET_SEC_ARGS: dict(
					lex_class_conj=[
						frozenset([
							'praet',
							'fin',
							'impt',
							'bedzie',
							'pred',
							'aglt',
							]),
						frozenset([
							'pri',
							'sec',
							]),
						],
					),
				})

	def opt_bigrams(self):
		self.features.append({
				_co.CFG_FET_NAME: 'bigrams',
				_co.CFG_FET_CLASS: 'ngramcount',
				_co.CFG_FET_SEC_ARGS: dict(
					n=2,
					),
				})

	def opt_trigrams(self):
		self.features.append({
				_co.CFG_FET_NAME: 'trigrams',
				_co.CFG_FET_CLASS: 'ngramcount',
				_co.CFG_FET_SEC_ARGS: dict(
					n=3,
					),
				})

	def opt_tok_count(self):
		self.features.append({
				_co.CFG_FET_NAME: 'tok_count',
				_co.CFG_FET_CLASS: 'tokencount'
				})

	def _ensure_lex_classes(self):
		if self._args_lex_classes is not None:
			return

		self._args_lex_classes = dict(
				limit_list=set(),
				grouping={},
				# also_count_ungrouped=True,
				)
		self.features.append({
				_co.CFG_FET_NAME: 'lex_classes',
				_co.CFG_FET_CLASS: 'lexclasscount',
				_co.CFG_FET_SEC_ARGS: self._args_lex_classes,
				})

	def _ensure_proper_names(self):
		if self._args_proper_names is not None:
			return

		self._args_proper_names = dict(
				grouping={},
				limit_to_groups=True,
				)
		self.features.append({
				_co.CFG_FET_NAME: 'proper_names',
				_co.CFG_FET_CLASS: 'propernamescount',
				_co.CFG_FET_SEC_ARGS: self._args_proper_names,
				})
