import time
from random import randint

"""
input: input file, patient_id
ouput: make output file
"""
def analyze(block_of_text):
	# hard code patient_id heh
	patient_id = ''.join(["%s" % randint(0, 9) for num in range(0, 10)])

	# random notes: can only ask each question once, must ask exactly word for word
	question_db = get_question_db()
	spoken_questions = get_spoken_questions(question_db)

	# header_info = "Patient name. Mike Jones. Interviewer name. Christina Zhu. Start interview."
	interview = block_of_text.split("Starts interview.")
	header_info = ""
	if len(interview) == 2:
		header_info = interview[0]
		block_of_text = interview[1]

	sentences = breakdown(block_of_text)
	qanda, dialogue = get_qanda(sentences, spoken_questions, question_db)

	doc_text = ""
	doc_text += generate_document_header(header_info, patient_id)
	doc_text +=  "\n=== Information ===\n"
	standard_text, standard_dict = generate_standard(qanda, question_db)
	doc_text += standard_text
	doc_text += "\n=== Full Interview Q&A ===\n"
	doc_text += generate_dialogue(dialogue)
	doc_text += "\n=== Feedback for Patient ===\n"
	doc_text += generate_feedback(standard_dict, question_db)
	doc_text += "\n\nGenerated by Airscribe"

	date = "160214"
	date = time.strftime("%y%m%d")
	print_to_document(doc_text, "pid{0}_discharge_{1}.txt".format(patient_id, date))

	# alternatively, return block of text
	return doc_text

"""
input: text file
output: list of sentences
"""
def breakdown(block_of_text):
	# note IBM watson has periods but no other punctuation
	sentences = block_of_text.strip().split(".")
	processed = []
	for s in sentences:
		s = s.strip()
		if len(s) > 0:
			processed.append(s)
	return processed

"""
input: list of sentences
output: dictionary of responses

qanda = {standardized_question : verbatim_answer}
dialogue = {verbatim_question : verbatim_answer}
"""
def get_qanda(sentences, spoken_questions, question_db):
	qanda = {}
	dialogue = {}
	curr_question = None
	curr_q_verbatim = None
	response = "" # usually an answer
	for sentence in sentences:
		# new question
		qid = match_qid(sentence.lower(), question_db)
		# sentence is a question
		if qid >= 0:
			# best match
			q = spoken_questions[qid]
			q_verbatim = sentence
			# q = sentence # go with verbatim instead of official spoken words
			# deal with prev question
			if curr_question:
				qanda[curr_question] = response
				dialogue[curr_q_verbatim] = response
			curr_question = q[0].upper() + q[1:] # capitalize first char
			curr_q_verbatim = q_verbatim
			response = ""
		# sentence is not a question
		else:
			response += sentence + ". "
	# last question
	if curr_question:
		qanda[curr_question] = response
		dialogue[curr_q_verbatim] = response
	return qanda, dialogue

"""
input: dictionary of responses
output: standard, formatted interview info
[text example]
Hometown:	Fremont
Lives alone:	Yes
[standard example]
{qid : answer}
"""
def generate_standard(qanda, question_db):
	# if we want the questions in a certain order, iterate through question_db in order
	text = ""
	standard = {}
	spoken_questions = get_spoken_questions(question_db)
	for question in qanda:
		# get the index from list of spoken_words
		# could use match_qid but let's not refactor now
		qid = spoken_questions.index(question.lower())
		standard_form = question_db[qid]['standard_form']
		answer = qanda[question]
		answer = standardize_answer(answer, question_db[qid]['answers'])
		text += "{0}:\t{1}\n".format(standard_form, answer)
		standard[qid] = answer
	return text, standard

"""
input: verbose answer, list of standard answers
output: one of the standard answers, or special custom answer
currently VERY simple; could use more thoughtful algorithm...
"""
def standardize_answer(answer, answer_choices):
	# if a key word (answer choice) is anywhere in their answer, capitalize and return it
	# otherwise just return the answer? or a special message?

	# also need to consider equivalent words like "yes" = "yeah"
	for choice in answer_choices:
		if choice.lower() in answer.lower():
			return choice.title()
	return answer

"""
input: dictionary of responses
output: summary of feedback
"""
def generate_feedback(standard, question_db):
	# standard
	# {qid : answer}
	text = ""
	for qid in standard:
		answer = standard[qid].lower()
		try:
			i = question_db[qid]['answers'].index(answer)
			if 'feedback' in question_db[qid]: # particular question has feedback
				feedback = question_db[qid]['feedback'][i]
				if len(feedback) > 0:
					text += "{}. ".format(feedback)
		except ValueError: # answer choice not in list; special answer
			continue
	if len(text.strip()) == 0: # no feedback
		text = "No special instructions."
	return "{}\n".format(text)

"""
input: dictionary of responses
ouput: dialogue format
"""
def generate_dialogue(qanda):
	text = ""
	for question in qanda:
		text += "Q: {}?\n".format(question)
		text += "A: {}\n".format(qanda[question])
	return text

"""
input: patient_id
output: patient details???
===
PATIENT ID:
PATIENT NAME:
"""
def generate_document_header(header_info, patient_id):
	# header_info = "Patient name. Mike Jones. Interviewer name. Christina Zhu. Start interview."
	patient_name = ""
	interviewer_name = ""
	date = time.strftime("%b %d, %Y")
	info = header_info.split(".")
	if len(info) >= 4:
		patient_name = info[1].strip()
		interviewer_name = info[3].strip()
	text = "Hospital Discharge Interview\nPATIENT ID: {0}\nPATIENT NAME: {1}\n".format(patient_id, patient_name) 
	text += "DATE: {0}\nINTERVIEWER: {1}\n".format(date, interviewer_name)
	return text

"""
input: dictionary of responses, optional summary?
output: print formatted text file
"""
def print_to_document(text, filename):
	with open(filename, 'w') as f:
		f.write(text)
	with open(filename, 'w') as f:
		f.write(text)

def get_question_db():
	# kinda sketch representation of Question struct
	# Question = {'qid' = int, spoken_form' = "how are you", 'standard_form'="Feelings", 'answers'=["good", "bad"]}
	question_db = []
	question_db.append({
			'qid' : 0,
			'spoken_form' : "what is your name",
			'key_word' : "name",
			'standard_form' : "Name", 
			'answers' : []})
	question_db.append({
			'qid' : 1,
			'spoken_form' : "how are you",
			'key_word' : "how are you",
			'standard_form' : "Feelings", 
			'answers' : ["good", "bad", "not good"]})
	question_db.append({
			'qid' : 2,
			'spoken_form' : "what city do you live in", # what city do you live in
			'key_word' : "city",
			'standard_form' : "Hometown", 
			'answers' : ["fremont", "san jose", "san francisco", "cupertino", "new york",
			"tokyo", "beijing", "palo alto", "berkeley", "paris", "toronto", "seattle",
			"walnut creek", "san mateo", "pasadena", "los angeles", "santa clara", "saratoga"]})
	question_db.append({
			'qid' : 3,
			'spoken_form' : "what kind of building is your home", 
			'key_word' : "building",
			'standard_form' : "Type of home", 
			'answers' : ["house", "apartment", "condo", "shack"]})
			# if apartment, check if there are stairs
	question_db.append({
			'qid' : 4,
			'spoken_form' : "do you live alone", # too similar to where do you live?
			'key_word' : "alone",
			'standard_form' : "Lives alone", 
			'answers' : ["yes", "no"],
			# if live alone, send check up
			'feedback' : ["Since patient lives alone, schedule weekly phone call to check in", ""]})
			# if live alone, send check up
	question_db.append({
			'qid' : 5,
			'spoken_form' : "do you have stairs in your house", 
			'key_word' : "stairs",
			'standard_form' : "Stairs in home", 
			'answers' : ["yes", "no"],
			# if stairs, weekly check up by medical assistant
			'feedback' : ["Since patient's home has stairs, consider assigning medical assistant for weekly check up", ""]})
	question_db.append({
			'qid' : 6,
			'spoken_form' : "do you have medical insurance", 
			'key_word' : "insurance",
			'standard_form' : "Has insurance", 
			'answers' : ["yes", "no"],
			'feedback' : ["", "Patient does not have health insurance; consult social workers"]})

	#print question_db
	return question_db

def get_spoken_questions(question_db):
	# just a list of all spoken form questions
	spoken_questions = []
	for question in question_db:
		spoken_questions.append(question['spoken_form'])
	return spoken_questions

def edit_distance(s1, s2):
    m=len(s1)+1
    n=len(s2)+1

    tbl = {}
    for i in range(m): tbl[i,0]=i
    for j in range(n): tbl[0,j]=j
    for i in range(1, m):
        for j in range(1, n):
            cost = 0 if s1[i-1] == s2[j-1] else 1
            tbl[i,j] = min(tbl[i, j-1]+1, tbl[i-1, j]+1, tbl[i-1, j-1]+cost)

    return tbl[i,j]

def word_edit_distance(str1, str2):
	words1 = str1.split()
	words2 = str2.split()
	dist = list(set(words1) - set(words2)) + list(set(words2) - set(words1))
	return len(dist)

def match_qid(sentence, question_db):
	i = 0
	for question in question_db:
		if question_db[i]['key_word'] in sentence:
			return i
		i += 1
	return -1 # no question match

# for testing; comment out if needed
if __name__ == "__main__":
	# sample workflow
	with open("input.txt", 'r') as f:
		block_of_text = f.readlines()[0]
	analyze(block_of_text)

