from __future__ import unicode_literals
import erpnext.education.utils as utils
import frappe

# LMS Utils to Update State for Vue Store
@frappe.whitelist()
def get_program_enrollments():
	student = utils.get_current_student()
	if student == None:
		return None
	try:
		student = frappe.get_doc("Student", student)
		return student.get_program_enrollments()
	except:
		return None

@frappe.whitelist()
def get_all_course_enrollments():
	student = utils.get_current_student()
	if student == None:
		return None
	try:
		student = frappe.get_doc("Student", student)
		return student.get_all_course_enrollments()
	except:
		return None

# Vue Client Functions
@frappe.whitelist(allow_guest=True)
def get_portal_details():
	"""
	Returns portal details from Education Settings Doctype. This contains the Title and Description for LMS amoung other things.
	"""
	from erpnext import get_default_company

	settings = frappe.get_doc("Education Settings")
	title = settings.portal_title or get_default_company()
	description = settings.description
	return dict(title=title, description=description)

@frappe.whitelist(allow_guest=True)
def get_featured_programs():
	featured_program_names = frappe.get_all("Program", filters={"is_published": True, "is_featured": True})
	if featured_program_names:
		featured_list = [utils.get_program(program['name']) for program in featured_program_names]
		return featured_list
	else:
		return get_all_programs()[:2]

@frappe.whitelist(allow_guest=True)
def get_all_programs():
	program_names = frappe.get_all("Program", filters={"is_published": True})
	if program_names:
		program_list = [utils.get_program(program['name']) for program in program_names]
		return program_list
	else:
		return None

@frappe.whitelist(allow_guest=True)
def get_program_details(program_name):
	try:
		program = frappe.get_doc('Program', program_name)
		return program
	except:
		return None

# Functions to get program & course details
@frappe.whitelist(allow_guest=True)
def get_courses(program_name):
	program = frappe.get_doc('Program', program_name)
	courses = program.get_course_list()
	return courses

@frappe.whitelist()
def get_next_content(current_content, current_content_type, topic):
	if frappe.session.user == "Guest":
		return None
	topic = frappe.get_doc("Topic", topic)
	content_list = [{'content_type':item.doctype, 'content':item.name} for item in topic.get_contents()]
	current_index = content_list.index({'content': current_content, 'content_type': current_content_type})
	try:
		return content_list[current_index + 1]
	except IndexError:
		return None

def get_quiz_with_answers(quiz_name):
	try:
		quiz = frappe.get_doc("Quiz", quiz_name).get_questions()
		quiz_output = [{'name':question.name, 'question':question.question, 'options':[{'name': option.name, 'option':option.option, 'is_correct':option.is_correct} for option in question.options]} for question in quiz]
		return quiz_output
	except:
		frappe.throw("Quiz {0} does not exist".format(quiz_name))
		return None

@frappe.whitelist()
def get_quiz_without_answers(quiz_name, course_name):
	try:
		quiz = frappe.get_doc("Quiz", quiz_name)
		questions = quiz.get_questions()
	except:
		frappe.throw("Quiz {0} does not exist".format(quiz_name))
		return None

	enrollment = utils.get_course_enrollment(course_name).name
	quiz_status = {}
	quiz_status['is_complete'], quiz_status['score'], quiz_status['result']  = utils.check_quiz_completion(quiz, enrollment)
	quiz_output = [{'name':question.name, 'question':question.question, 'type': question.type, 'options':[{'name': option.name, 'option':option.option} for option in question.options]} for question in questions]
	return { 'quizData': quiz_output, 'status': quiz_status}

@frappe.whitelist()
def evaluate_quiz(course, quiz_response, quiz_name):
	"""LMS Function: Evaluates a simple multiple choice quiz.
	:param quiz_response: contains user selected choices for a quiz in the form of a string formatted as a dictionary. The function uses `json.loads()` to convert it to a python dictionary.
	"""
	import json
	quiz_response = json.loads(quiz_response)
	quiz = frappe.get_doc("Quiz", quiz_name)
	answers, score, status = quiz.evaluate(quiz_response, quiz_name)

	result = {k: ('Correct' if v else 'Wrong') for k,v in answers.items()}
	result_data = []
	for key in answers:
		item = {}
		item['question'] = key
		item['quiz_result'] = result[key]
		try:
			if isinstance(quiz_response[key], list):
				item['selected_option'] = ', '.join(frappe.get_value('Options', res, 'option') for res in quiz_response[key])
			else:
				item['selected_option'] = frappe.get_value('Options', quiz_response[key], 'option')
		except:
			item['selected_option'] = "Unattempted"
		result_data.append(item)

	add_quiz_activity(course, quiz_name, result_data, score, status)
	return(score)

def add_quiz_activity(course, quiz_name, result_data, score, status):
	if not utils.get_current_student():
		return None
	enrollment = utils.get_course_enrollment(course).name
	quiz_activity = frappe.get_doc({
		"doctype": "Quiz Activity",
		"enrollment": enrollment,
		"quiz": quiz_name,
		"activity_date": frappe.utils.datetime.datetime.now(),
		"result": result_data,
		"score": score,
		"status": status
		}).insert()

@frappe.whitelist()
def enroll_in_program(program_name):
	if(not utils.get_current_student()):
		utils.create_student_from_current_user()
	student = frappe.get_doc("Student", utils.get_current_student())
	program_enrollment = student.enroll_in_program(program_name)
	return program_name

# Academty Activity
@frappe.whitelist()
def add_activity(course, content_type, content):
	if not utils.get_current_student():
		return
	enrollment = utils.get_course_enrollment(course)
	if(utils.check_activity_exists(enrollment.name, content_type, content)):
		pass
	else:
		activity = frappe.get_doc({
			"doctype": "Course Activity",
			"enrollment": enrollment.name,
			"content_type": content_type,
			"content": content,
			"activity_date": frappe.utils.datetime.datetime.now()
			})
		activity.save()
		frappe.db.commit()

@frappe.whitelist()
def get_course_meta(course_name, program_name):
	"""
	Return the porgress of a course in a program as well as the content to continue from.
		:param course_name:
		:param program_name:
	"""
	if not utils.get_current_student():
		return {'flag':'Start Course' }
	course_enrollment = utils.get_course_enrollment(course_name)
	program_enrollment = utils.get_program_enrollment(program_name)
	student = frappe.get_doc("Student", utils.get_current_student())
	if not program_enrollment:
		return None
	if not course_enrollment:
		course_enrollment = utils.enroll_in_course(course_name, program_name)
	progress = course_enrollment.get_progress(student)
	count = sum([activity['is_complete'] for activity in progress])
	if count == 0:
		return {'flag':'Start Course'}
	elif count == len(progress):
		return {'flag':'Completed'}
	elif count < len(progress):
		next_item = next(item for item in progress if item['is_complete']==False)
		return {'flag':'Continue'}

@frappe.whitelist()
def get_topic_meta(topic_name, course_name):
	"""
	Return the porgress of a course in a program as well as the content to continue from.
		:param topic_name:
		:param course_name:
	"""
	topic = frappe.get_doc("Topic", topic_name)
	if not utils.get_current_student():
		topic_content = topic.get_all_children()
		if topic_content:
			return {'flag':'Start Course', 'content_type': topic_content[0].content_type, 'content': topic_content[0].content}
		else:
			return None
	course_enrollment = utils.get_course_enrollment(course_name)
	student = frappe.get_doc("Student", utils.get_current_student())
	progress = student.get_topic_progress(course_enrollment.name, topic)
	if not progress:
		return { 'flag':'Start Topic', 'content_type': None, 'content': None }
	count = sum([activity['is_complete'] for activity in progress])
	if count == 0:
		return {'flag':'Start Topic', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']}
	elif count == len(progress):
		return {'flag':'Completed', 'content_type': progress[0]['content_type'], 'content': progress[0]['content']}
	elif count < len(progress):
		next_item = next(item for item in progress if item['is_complete']==False)
		return {'flag':'Continue', 'content_type': next_item['content_type'], 'content': next_item['content']}

@frappe.whitelist()
def get_program_progress(program_name):
	import math
	program = frappe.get_doc("Program", program_name)
	program_enrollment = utils.get_program_enrollment(program_name)
	program_meta = {}
	if not program_enrollment:
		return None
	else:
		progress = []
		for course in program.get_all_children():
			meta = get_course_meta(course.course, program_name)
			is_complete = False
			if meta['flag'] == "Completed":
				is_complete = True
			progress.append({'course_name': course.course_name, 'name': course.course, 'is_complete': is_complete})

		program_meta['progress'] = progress
		program_meta['name'] = program_name
		program_meta['program'] = program.program_name

		try:
			program_meta['percentage'] = math.ceil((sum([item['is_complete'] for item in progress] * 100)/len(progress)))
		except ZeroDivisionError:
			program_meta['percentage'] = 0

		return program_meta

@frappe.whitelist()
def get_joining_date():
	current_student = utils.get_current_student()
	if(current_student):
		student = frappe.get_doc("Student", current_student)
		return student.joining_date
	else:
		return None

@frappe.whitelist()
def get_quiz_progress(program_name):
	program = frappe.get_doc("Program", program_name)
	program_enrollment = utils.get_program_enrollment(program_name)
	quiz_meta = frappe._dict()
	student = frappe.get_doc("Student", utils.get_current_student())
	if not program_enrollment:
		return None
	else:
		progress_list = []
		for course in program.get_all_children():
			course_enrollment = utils.get_course_enrollment(course.course)
			meta = course_enrollment.get_progress(student)
			for progress_item in meta:
				# if progress_item['content_type'] == "Quiz" and progress_item['is_complete'] == True:
				if progress_item['content_type'] == "Quiz":
					progress_item['course'] = course.course_name
					progress_list.append(progress_item)
		if not progress_list:
			return None
		quiz_meta.quiz_attempt = progress_list
		quiz_meta.name = program_name
		quiz_meta.program = program.program_name
		return quiz_meta


@frappe.whitelist(allow_guest=True)
def get_course_details(course_name):
	try:
		course = frappe.get_doc('Course', course_name)
		return course
	except:
		return None

# Functions to get program & course details
@frappe.whitelist(allow_guest=True)
def get_topics(course_name):
	course = frappe.get_doc('Course', course_name)
	topics = course.get_topics()
	return topics

@frappe.whitelist()
def get_content(type, content):
	try:
		return frappe.get_doc(type, content)
	except:
		return None