import os
import sys
import csv
import random
import unicodedata
import pandas as pd
import numpy as np
import math

import store_data

_thisDir = os.path.dirname(os.path.abspath(__file__)).decode(sys.getfilesystemencoding())
_parentDir = os.path.abspath(os.path.join(_thisDir, os.pardir))
dataDir = _parentDir + '/data/'

"""
Returns a list of all stimuli in the stim folder (assuming all the .jpg files are stimulus images)
"""
def get_stimuli(folder, prepend, fileextension):
	'''
	get array of stimuli from the directory name stim
	'''
	stimuli = []
	for stimulusFile in os.listdir(_parentDir + folder):
		if stimulusFile.endswith(fileextension): 
			stimuli.append(prepend + stimulusFile[:-4])
	return stimuli

def get_foodq():
	info = pd.read_csv(_thisDir + '/FoodQuestions.csv')
	questions=info['Question']
	leftText=info['LeftText']
	middleText=info['MiddleText']
	rightText=info['RightText']
	new_info=[]
	for i in range(0,len(questions)):
		q = questions[i]
		l=leftText[i]
		if type(l) == float:
			l=''
		m=middleText[i]
		if type(m) == float:
			m=''
		r=rightText[i]
		if type(r) == float:
			r=''
		new_info.append({'question':q,'leftText':l,'middleText':m,'rightText':r})
	return new_info

"""
Creates list of dictionaries where each dictionary holds the variables for one trial
"""
def get_ratingtask_expVariables(stimFolder, demo):
	stimuli = get_stimuli(stimFolder,'','.jpg')

	expVariables = [] # array of dictionaries

	foodq = get_foodq()
	random.shuffle(foodq);

	for j in range(0, len(foodq)):
		random.shuffle(stimuli)
		for i in range(0,len(stimuli)):
			question = foodq[j]['question']
			leftRatingText = foodq[j]['leftText']
			middleRatingText = foodq[j]['middleText']
			rightRatingText = foodq[j]['rightText']
			rs_min=0
			rs_max=10
			rs_tickIncrement=1
			rs_increment=0.01
			rs_labelNames=["", "", "", "", "", "", "", "", "", "", ""]
			expVariables.append({'stimulus':stimuli[i], 'fullStimName':stimuli[i]+'.jpg', 'question':question, 'leftRatingText':leftRatingText, 'middleRatingText':middleRatingText, 'rightRatingText':rightRatingText, 'rs_min':rs_min, 'rs_max':rs_max, 'rs_tickIncrement':rs_tickIncrement, 'rs_increment':rs_increment, 'rs_labelNames':rs_labelNames})
	return expVariables

"""
Get demographic questions
Returns dictionary with keys as index of question
Values are dictionaries with questions as keys and the values are a list of options
"""
def get_demographicq():
	info = pd.read_csv(_thisDir + '/DemographicQuestions.csv')
	questions=info['Question']
	info=info.set_index('Question')
	new_info=[]
	for j in range(0,len(questions)):
		q = questions[j]
		tmp=info.loc[q].values
		options=[]
		for i in tmp:
			if type(i) != float: # remove nan values
				options.append(i)
		new_info.append({q:options})
	return new_info

def get_TFEQr18():
	info = pd.read_csv(_thisDir + '/TFEQr18.csv')
	questions=info['Question']
	option1=info['Option1']
	option2=info['Option2']
	option3=info['Option3']
	option4=info['Option4']
	return questions, option1, option2, option3, option4

def get_EAT26():
	info = pd.read_csv(_thisDir + '/EAT26.csv')
	questions=info['Question']
	option1=info['Option1']
	option2=info['Option2']
	option3=info['Option3']
	option4=info['Option4']
	option5=info['Option5']
	option6=info['Option6']
	return questions, option1, option2, option3, option4, option5, option6

neutralDimensions = {'taste':'How TASTY is this food?','health':'How HEALTHY is this food?'}

"""
Returns a dictionary of the stimuli as keys and their bids as values
csv_name is the location + name of the csv file where the bids are located
The csv must have the stimulus name in a column with the heading "stimulus"
	the bid must be in a column with the heading "rating"
# dim is dimension - key in neutralDimensions
"""
def get_bid_responses(dim, csv_name):
	'''
	from a csv file generated by the auction task, generate a dictionary of the stimuli and the participant's bids
	'''
	df = pd.read_csv(csv_name)
	df = df.loc[df['question']==neutralDimensions[dim]]
	stim = df.loc[:,'stimulus']
	bids = df.loc[:,'rating']
	stimBidDF = pd.concat([bids,stim],axis=1)
	stimBidDF = stimBidDF.rename(index=str, columns={"rating": "rating", "stimulus": "stimulus"})
	return stimBidDF


def find_common_items(l1,l2):
	print l1
	print l2
	commonItems=[]
	for item in l1:
		if item in l2:
			commonItems.append(item)
	print commonItems
	return commonItems

def get_common_item(l1,l2):
	commonItems=find_common_items(l1,l2)
	if len(commonItems) != 0: # found reference item based on HEALTH and +1 positive on TASTE
		random.shuffle(commonItems)
		referenceItem=commonItems[0]
		return referenceItem
	return None

def get_choicetask_expVariables(expID, subjectID, stimFolder, defaultRefItem, demo):
	if demo:
		refItem = 'tomato'
	else:
		# check if get_reference_item was already called when instructions display was created
		if os.path.exists(os.path.join(dataDir,expID,subjectID,subjectID+'_ReferenceItem.csv')):
			print "EXISTS"
			df=pd.read_csv(os.path.join(dataDir,expID,subjectID,subjectID+'_ReferenceItem.csv'))
			refItem=df['reference_item'].values[-1]
		else:
			refItem = get_reference_item(expID,subjectID,defaultRefItem)
	stimuli = get_stimuli(stimFolder,'','.jpg')
	random.shuffle(stimuli)
	expVariables = []
	for stim in stimuli:
		if stim != refItem:
			leftRatingText = 'Strongly prefer reference'
			middleRatingText = 'Neutral'
			rightRatingText = 'Strongly prefer food'
			rs_min=0
			rs_max=10
			rs_tickIncrement=1
			rs_increment=0.01
			rs_labelNames=["", "", "", "", "", "", "", "", "", "", ""]
			expVariables.append({"question":"Do you prefer the reference item on the left or the food on the right?", "referenceItem":refItem,"secondFoodItem":stim,"fullReferenceItemName":refItem+".jpg", "fullSecondFoodItemName":stim+".jpg", 'leftRatingText':leftRatingText, 'middleRatingText':middleRatingText, 'rightRatingText':rightRatingText, 'rs_min':rs_min, 'rs_max':rs_max, 'rs_tickIncrement':rs_tickIncrement, 'rs_increment':rs_increment, 'rs_labelNames':rs_labelNames})
	return expVariables

def get_reference_item(expID,subjectID,defaultRefItem):
	taste=get_bid_responses('taste', dataDir + '/' + expID + '/' + subjectID+'/'+subjectID+'_RatingsResults.csv')
	health=get_bid_responses('health', dataDir + '/' + expID + '/' + subjectID+'/'+subjectID+'_RatingsResults.csv')
	taste=taste.sort_values("rating")
	health=health.sort_values("rating")
	taste.reset_index(drop=True,inplace=True)
	health.reset_index(drop=True,inplace=True)
	sorted_taste=taste['stimulus'].values
	sorted_health=health['stimulus'].values
	nStim=len(taste)
	binSize = int(math.ceil(nStim / 5.0)) # round up
	midBin = int(nStim/binSize)/2 # round down

	midBinIndices = [binSize*midBin,binSize*(midBin+1)]
	neutral_taste=sorted_taste[midBinIndices[0]:midBinIndices[1]]
	neutral_health=sorted_health[midBinIndices[0]:midBinIndices[1]]

	refItemInfo = []

	referenceItem = None
	if referenceItem == None:
		# neutral TASTE and HEALTH
		print 'neutral on TASTE and HEALTH'
		referenceItem=get_common_item(neutral_taste,neutral_health)
		refItemInfo.append({'bin_1_type':'TASTE','bin_2_type':'HEALTH','bin_1_items':neutral_taste,'bin_2_items':neutral_health,'reference_item':referenceItem})
	
	if referenceItem == None:
		# find neutral on HEALTH and +1 on TASTE
		bin_plus1Indices=midBinIndices = [binSize*(midBin+1),binSize*(midBin+2)]
		taste_plus1=sorted_taste[midBinIndices[0]:midBinIndices[1]]
		print 'neutral on HEALTH and +1 on TASTE'
		referenceItem=get_common_item(taste_plus1,neutral_health)
		refItemInfo.append({'bin_1_type':'+1 TASTE','bin_2_type':'HEALTH','bin_1_items':taste_plus1,'bin_2_items':neutral_health,'reference_item':referenceItem})
	
	if referenceItem == None:
		# neutral HEALTH & -1 on TASTE
		bin_minus1Indices=midBinIndices = [binSize*(midBin-1),binSize*(midBin)]
		taste_minus1=sorted_taste[midBinIndices[0]:midBinIndices[1]]
		print 'neutral HEALTH & -1 on TASTE'
		referenceItem=get_common_item(taste_minus1,neutral_health)
		refItemInfo.append({'bin_1_type':'-1 TASTE','bin_2_type':'HEALTH','bin_1_items':taste_minus1,'bin_2_items':neutral_health,'reference_item':referenceItem})
	
	if referenceItem == None:
		# neutral TASTE & +1 HEALTH
		print 'neutral TASTE & +1 HEALTH'
		bin_plus1Indices=midBinIndices = [binSize*(midBin+1),binSize*(midBin+2)]
		health_plus1=sorted_health[midBinIndices[0]:midBinIndices[1]]
		referenceItem=get_common_item(neutral_taste,health_plus1)
		refItemInfo.append({'bin_1_type':'TASTE','bin_2_type':'+1 HEALTH','bin_1_items':neutral_taste,'bin_2_items':health_plus1,'reference_item':referenceItem})
	
	if referenceItem == None:
		# neutral TASTE, -1 on HEALTH
		print 'neutral TASTE, -1 on HEALTH'
		bin_minus1Indices=midBinIndices = [binSize*(midBin-1),binSize*(midBin)]
		health_minus1=sorted_taste[midBinIndices[0]:midBinIndices[1]]
		referenceItem=get_common_item(neutral_taste,health_minus1)
		refItemInfo.append({'bin_1_type':'TASTE','bin_2_type':'-1 HEALTH','bin_1_items':neutral_taste,'bin_2_items':health_minus1,'reference_item':referenceItem})

	if referenceItem == None:
		# otherwise return saltines
		referenceItem = defaultRefItem
		refItemInfo.append({'bin_1_type':'None','bin_2_type':'None','bin_1_items':[],'bin_2_items':[],'reference_item':referenceItem})
	
	if subjectID.startswith(expID):
		filePath = dataDir + expID + '/' + subjectID + '/'
		store_data.results_to_csv(expID, subjectID, filePath, 'ReferenceItem.csv', refItemInfo, {})
	return referenceItem


"""
Checks request.args has assignmentId, hitId, turkSubmitTo, workerId, live - all but live is passed by MTurk
live refers to whether HIT is live or in sandbox
"""
def contains_necessary_args(args):
	if 'workerId' in args and 'assignmentId' in args and 'hitId' in args and 'turkSubmitTo' in args and 'live' in args:
		return True
	else:
		return False

"""
Retrieve necessary args: assignmentId, hitId, turkSubmitTo, workerId, live
"""
def get_necessary_args(args):
	workerId = args.get('workerId')
	assignmentId = args.get('assignmentId')
	hitId = args.get('hitId')
	turkSubmitTo = args.get('turkSubmitTo')
	live = args.get('live') == "True"
	return [workerId, assignmentId, hitId, turkSubmitTo, live]