package com.infinite.focus.server.dashboard.userstats;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.infinite.focus.server.auth.AccountRepository;
import com.infinite.focus.server.auth.Instructor;
import com.infinite.focus.server.auth.InstructorRepository;
import com.infinite.focus.server.auth.Student;
import com.infinite.focus.server.auth.StudentRepository;
import com.infinite.focus.server.activity.Activity;
import com.infinite.focus.server.activity.Activity_;
import com.infinite.focus.server.activity.service.ActivityService;
import com.infinite.focus.server.dashboard.DashboardController;
import com.infinite.focus.server.dashboard.DemographicType;
import com.infinite.focus.server.dashboard.GetDataDashBoardRequest;
import com.infinite.focus.server.dashboard.LabelAndValue;
import com.infinite.focus.server.dashboard.TimeLine;
import com.infinite.focus.server.grade.Grade;
import com.infinite.focus.server.grade.GradeRepository;
import com.infinite.focus.server.home.MoodUpdate;
import com.infinite.focus.server.standard.Standard;
import com.infinite.focus.server.standard.StandardRepository;
import com.infinite.focus.server.standard.Standard_;
import com.infinite.focus.server.students.ClassRepository;
import com.infinite.focus.server.students.Student_;
import com.infinite.focus.server.students.service.StudentService;
import com.infinite.focus.server.tests.SocioEmotionalTestResult;
import com.infinite.focus.server.tests.SocioEmotionalTestResult_;
import com.infinite.focus.server.utils.AppUtils;
import com.infinite.focus.server.utils.DateUtils;
import com.infinite.focus.server.utils.DigitUtils;

@Service
public class UserStatsServiceImpl implements UserStatsService {

	@Autowired
	EntityManager entityManager;
	
	@Autowired
	AccountRepository accountRepository;
	
	@Autowired
	GradeRepository gradeRepository;
	
	@Autowired
	StandardRepository standardRepository;

	@Autowired
	StudentRepository studentRepository;

	@Autowired
	InstructorRepository instructorRepository;

	@Autowired
	ClassRepository classRepository;
	
	@Autowired
	ActivityService activityService;
	
	@Autowired
	StudentService studentService;

	String forwardSlash = "/";

	@Override
	public LinkedHashMap<String, LinkedList<Object>> getOverall(GetDataDashBoardRequest request) {

		System.out.println("-----------------------OVERALL-----------------------------");

		long studentCount = studentRepository.count();
		long instructorCount = instructorRepository.count();

		long totalCount = studentCount + instructorCount;

		System.out.println("Stduent's count					" + studentCount);
		System.out.println("Instructor's count				" + instructorCount);
		System.out.println("------------------------------------------------------------");
		System.out.println("Total count					" + totalCount);

		BigDecimal avgStudents = DigitUtils.getPercentageBigDecimal(studentCount, totalCount);

		BigDecimal avgInstructors = DigitUtils.getPercentageBigDecimal(instructorCount, totalCount);

		System.out.println("------------------------------------------------------------");
		System.out.println("---------Percentage = (Value " + forwardSlash + " Total Value) � 100-----------");
		System.out.println("Average Stduents				" + avgStudents);
		System.out.println("Average Instructors				" + avgInstructors);

		LinkedHashMap<String, LinkedList<Object>> graphData = new LinkedHashMap<String, LinkedList<Object>>();

		LinkedList<Object> studentsList = new LinkedList<Object>();
		studentsList.add(studentCount);
		studentsList.add(avgStudents);
		graphData.put("Students", studentsList);

		LinkedList<Object> instructorsList = new LinkedList<Object>();
		instructorsList.add(instructorCount);
		instructorsList.add(avgInstructors);
		graphData.put("Instructors", instructorsList);

		return graphData;
	}

	@Override
	public LinkedHashMap<String, LinkedList<Object>> getTeachers(GetDataDashBoardRequest request) {

		System.out.println("------------------------------------ TEACHERS ---------------------------------------");

		
		return getTeachersByGrade(request);
	}

	public LinkedHashMap<String, LinkedList<Object>> getTeachersByGrade(GetDataDashBoardRequest request) {

		System.out.println("------------------------------------ TEACHERS BY GRADE ---------------------------------------");

		List<Grade> grades = gradeRepository.findAll();

		LinkedHashMap<String, Long> gradeAndCountMap = new LinkedHashMap<String, Long>();

		Long totalCount = 0L;

		for (int i = 0; i < grades.size(); i++) {

			String key = grades.get(i).getGrade_name();

			Long count = instructorRepository.getCountByGradeId(grades.get(i).getGrade_id());

			totalCount = totalCount + count;

			gradeAndCountMap.put(key, count);

			System.out.println(key + " 				" + count);
		}

		System.out.println("-----------------------------------------------------------------------------");
		System.out.println("Total" + " 				" + totalCount);

		System.out.println(
				"----------------Percentage = (Value " + forwardSlash + " Total Value) � 100---------------------");

		LinkedHashMap<String, LinkedList<Object>> graphData = new LinkedHashMap<String, LinkedList<Object>>();

		Double totalPercentage = 0.0;

		for (String key : gradeAndCountMap.keySet()) {

			LinkedList<Object> list = new LinkedList<Object>();

			Long count = gradeAndCountMap.get(key);

			list.add(count);

			BigDecimal percentag = DigitUtils.getPercentageBigDecimal(count, totalCount);

			list.add(percentag);

			totalPercentage = totalPercentage + percentag.doubleValue();

			System.out.println(key + " 				" + count + "		" + totalCount + "		" + percentag);

			graphData.put(key, list);
		}

		totalPercentage = DigitUtils.formatDouble(totalPercentage);

		LinkedList<Object> list = new LinkedList<Object>();
		list.add(totalCount);
		list.add(DigitUtils.formatBigDecimal(new BigDecimal(totalPercentage)));

		graphData.put("Total", list);

		System.out.println("-----------------------------------------------------------------------------");
		System.out.println(
				"Total" + " 				" + totalCount + "		" + totalCount + "		" + totalPercentage);

		return graphData;
	}
	
	@Override
	public LinkedHashMap<String, LinkedHashMap<String, LinkedList<Object>>> getStudents(GetDataDashBoardRequest request) {
		
		System.out.println("------------------------------User Stats's Student --------------------------------");
		
		List<Student> students = studentRepository.findAllOrderById();
		
		System.out.println("Students - " + students.size());
		
		Date fromDate = AppUtils.isNullOrEmpty(students) ? DateUtils.setTimeToFromDate(new Date()) : DateUtils.setTimeToFromDate(students.get(0).getAccount().getCreatedAt());
		Date toDate = DateUtils.setTimeToToDate(new Date());// students.get(students.size() - 1).getAccount().getCreatedAt();
		
		LinkedHashMap<String, LinkedHashMap<String, LinkedList<Object>>> graphData = new LinkedHashMap<String, LinkedHashMap<String, LinkedList<Object>>>();
		
		System.out.println("----------------------------- Gender------------------------------");
		
		if (AppUtils.isNotNullOrEmpty(request.getGenders())) {

			LinkedHashMap<String, LinkedList<Object>> genders = new LinkedHashMap<String, LinkedList<Object>>();
			
			for (String gender : request.getGenders()) {

				System.out.println("----------------------------- "+ gender + "------------------------------");
				
				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
								request);
				getDataDashBoardRequest.getGenders().add(gender);
				
				genders.put(gender, getStudent(getDataDashBoardRequest, fromDate, toDate));
			}
			
			graphData.put("Gender", genders);
			
		} 
		
		System.out.println("----------------------------- Age ------------------------------");
		
		if (AppUtils.isNotNullOrEmpty(request.getAges())) {

			LinkedHashMap<String, LinkedList<Object>> ages = new LinkedHashMap<String, LinkedList<Object>>();
			
			for (Integer age : request.getAges()) {

				System.out.println("----------------------------- "+ age + "------------------------------");
				
				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
								request);
				getDataDashBoardRequest.getAges().add(age);
				
				ages.put(String.valueOf(age), getStudent(getDataDashBoardRequest, fromDate, toDate));
			}
			
			graphData.put("Age", ages);
		} 
		
		System.out.println("----------------------------- Ethnicity------------------------------");
		
		if (AppUtils.isNotNullOrEmpty(request.getEthnicity())) {

			LinkedHashMap<String, LinkedList<Object>> ethnicityMap = new LinkedHashMap<String, LinkedList<Object>>();
			
			for (String ethnicity : request.getEthnicity()) {
				
				System.out.println("----------------------------- "+ ethnicity + "------------------------------");
				
				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);

				getDataDashBoardRequest.getEthnicity().add(ethnicity);

				ethnicityMap.put(ethnicity, getStudent(getDataDashBoardRequest, fromDate, toDate));
			}
			
			graphData.put("Ethnicity", ethnicityMap);
			
		} 
		
		
		System.out.println("----------------------------- Grade------------------------------");
		
		if (AppUtils.isNotNullOrEmpty(request.getGradeIds())) {
			
			LinkedHashMap<String, LinkedList<Object>> grades = new LinkedHashMap<String, LinkedList<Object>>();
			
			for (Long grade_id : request.getGradeIds()) {
				
				System.out.println("-----------------------------" + grade_id +"------------------------------");


				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);
				
				getDataDashBoardRequest.getGradeIds().add(grade_id);

				grades.put(gradeRepository.getOne(grade_id).getGrade_name(), getStudent(getDataDashBoardRequest, fromDate, toDate));
			}
			
			graphData.put("Grade", grades);
			
		} 
		
		System.out.println("----------------------------- Classroom ------------------------------");
		
		if (AppUtils.isNotNullOrEmpty(request.getClassIds())) {
			
			LinkedHashMap<String, LinkedList<Object>> classrooms = new LinkedHashMap<String, LinkedList<Object>>();
			
			for (Long class_id : request.getClassIds()) {
				
				System.out.println("-----------------------------" + class_id +"------------------------------");


				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);
				
				getDataDashBoardRequest.getClassIds().add(class_id);
				
				classrooms.put(DashboardController.getClassNameWithInstructorFullName(class_id, classRepository, instructorRepository), getStudent(getDataDashBoardRequest, fromDate, toDate));
			}
			
			graphData.put("Classroom", classrooms);
			
		} 
				
		return graphData;
	}
	
	public LinkedList<Object> getStudent(GetDataDashBoardRequest request, Date fromDate, Date toDate) {

		List<Long> student_ids = studentService.getStudentByDemographics(request);

		LinkedList<Object> reportings = new LinkedList<Object>();

		if(AppUtils.isNotNullOrEmpty(student_ids)) {
			
			Double size = (double) student_ids.size();
			
			System.out.println("Student List Size - " + size + " FromDate - " + DateUtils.dailyDateFormat.format(fromDate) + " ToDate - " + DateUtils.dailyDateFormat.format(toDate));
			
			System.out.println("----------------------------Daily---------------------------------");
			
			Double days = (double) DateUtils.getDayCountByFromDateAndToDate(fromDate, toDate);
			
			BigDecimal dailyReporting = DigitUtils.getAverageBigDecimal(size, days); 

			System.out.println("dailyReporting - " +  dailyReporting + " = Size: " + size + " / Days: " + days);
			
			reportings.add(dailyReporting); //
			
			System.out.println("----------------------------Weekly---------------------------------");
			
			Double weeks = (double) DateUtils.getWeekCountByFromDateAndToDate(fromDate, toDate);
			
			BigDecimal weeklyReporting = DigitUtils.getAverageBigDecimal(size, weeks); 
						
			System.out.println("weeklyReporting - " +  weeklyReporting + " = Size: " + size + " / Weeks: " + weeks);
			
			reportings.add(weeklyReporting);
			
			System.out.println("----------------------------Monthly---------------------------------");
			
			Double months = (double) DateUtils.getMonthCountByFromDateAndToDate(fromDate, toDate);
			
			BigDecimal monthlyReporting = DigitUtils.getAverageBigDecimal(size, months); 
			
			System.out.println("monthlyReporting - " +  monthlyReporting + " = Size: " + size + " / Months: " + months);
			
			reportings.add(monthlyReporting);
			
			System.out.println("----------------------------Yearly---------------------------------");
			
			Double years = (double) DateUtils.getYearCountByFromDateAndToDate(fromDate, toDate);
			
			BigDecimal yearlyReporting = DigitUtils.getAverageBigDecimal(size, years); 
						
			System.out.println("yearlyReporting - " +  yearlyReporting + " = Size: " + size + " / Years: " + years);
			
			reportings.add(yearlyReporting);

		} else {
			
			reportings.add(DigitUtils.formateZeroToBigDecimal());
			reportings.add(DigitUtils.formateZeroToBigDecimal());
			reportings.add(DigitUtils.formateZeroToBigDecimal());
			reportings.add(DigitUtils.formateZeroToBigDecimal());
		}
		
		return reportings;
	}

	@Override
	public LinkedHashMap<String, LinkedList<Object>> getStudentsAndDemographicStrands(GetDataDashBoardRequest request) {

		switch (request.getDemographicType()) {
		case GENDER: {
			return getStudentsCountByGenders(request);
		}
		case AGE: {
			return getStudentsCountByAges(request);
		}
		case ETHNICITY: {
			return getStudentsCountByEthnicity(request);
		}
		case GRADE: {
			return getStudentsCountByGrades(request);
		}
		case CLASSROOM: {
			return getStudentsCountByClassrooms(request);
		}
		}

		return new LinkedHashMap<String, LinkedList<Object>>();
	}

	public LinkedHashMap<String, LinkedList<Object>> getStudentsCountByGenders(GetDataDashBoardRequest request) {

		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();

		Double totalCount = 0.0;

		List<String> genders = request.getGenders();

		for (int i = 0; i < genders.size(); i++) {

			String key = genders.get(i);

			Long count = studentRepository.getCountByGender(key);

			totalCount = totalCount + count;

			LinkedList<Object> list = new LinkedList<Object>();
			list.add(count);
			list.add(0);

			countAndAvgMap.put(key, list);
		}

		DigitUtils.addTotalInMapBigDecimal(countAndAvgMap, totalCount);

		return countAndAvgMap;
	}

	public LinkedHashMap<String, LinkedList<Object>> getStudentsCountByEthnicity(GetDataDashBoardRequest request) {

		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();

		Double totalCount = 0.0;

		List<String> ethnicity = request.getEthnicity();

		for (int i = 0; i < ethnicity.size(); i++) {

			String key = ethnicity.get(i);

			Long count = studentRepository.getCountByEthnicity(key);

			totalCount = totalCount + count;

			LinkedList<Object> list = new LinkedList<Object>();
			list.add(count);
			list.add(0);

			countAndAvgMap.put(key, list);
		}

		DigitUtils.addTotalInMapBigDecimal(countAndAvgMap, totalCount);

		return countAndAvgMap;
	}

	public LinkedHashMap<String, LinkedList<Object>> getStudentsCountByAges(GetDataDashBoardRequest request) {

		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();

		Double totalCount = 0.0;

		List<Integer> age = request.getAges();

		for (int i = 0; i < age.size(); i++) {

			Integer key = age.get(i);

			Long count = studentRepository.getCountByAge(key);

			totalCount = totalCount + count;

			LinkedList<Object> list = new LinkedList<Object>();
			list.add(count);
			list.add(0);

			countAndAvgMap.put(String.valueOf(key), list);
		}

		DigitUtils.addTotalInMapBigDecimal(countAndAvgMap, totalCount);

		return countAndAvgMap;
	}

	public LinkedHashMap<String, LinkedList<Object>> getStudentsCountByGrades(GetDataDashBoardRequest request) {

		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();

		Double totalCount = 0.0;

		List<Long> grade_ids = request.getGradeIds();

		for (int i = 0; i < grade_ids.size(); i++) {

			Long key = grade_ids.get(i);

			Long count = studentRepository.getCountByGradeId(key);

			totalCount = totalCount + count;

			LinkedList<Object> list = new LinkedList<Object>();
			list.add(count);
			list.add(0);

			countAndAvgMap.put(gradeRepository.getOne(key).getGrade_name(), list);
		}

		DigitUtils.addTotalInMapBigDecimal(countAndAvgMap, totalCount);
		
		return countAndAvgMap;
	}
	
	public LinkedHashMap<String, LinkedList<Object>> getStudentsCountByClassrooms(GetDataDashBoardRequest request) {

		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();

		Double totalCount = 0.0;

		List<Long> classrooms = request.getClassIds();

		for (int i = 0; i < classrooms.size(); i++) {

			Long key = classrooms.get(i).longValue();

			Long count = studentRepository.getCountByClassId(key);

			totalCount = totalCount + count;

			LinkedList<Object> list = new LinkedList<Object>();
			list.add(count);
			list.add(0);

			countAndAvgMap.put(DashboardController.getClassNameWithInstructorFullName(key, classRepository, instructorRepository), list);
		}

		DigitUtils.addTotalInMapBigDecimal(countAndAvgMap, totalCount);
		
		return countAndAvgMap;
	}

	@Override
	public LinkedList<LabelAndValue> getLogiAttemptsStudentsData(GetDataDashBoardRequest request) {
		return  getLogiAttemptsStudents(request);
	}
	
	/*@Override
	public LinkedHashMap<String, List<LabelAndValue>> getLogiAttemptsStudentsData(GetDataDashBoardRequest request) {
		
		LinkedHashMap<String, List<LabelAndValue>> graphData = new LinkedHashMap<String, List<LabelAndValue>>();

		if (AppUtils.isNotNullOrEmpty(request.getGenders())) {

			for (String gender : request.getGenders()) {

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);
				
				getDataDashBoardRequest.getGenders().add(gender);

				graphData.put(gender, getLogiAttemptsStudents(getDataDashBoardRequest));
			}
		} else if (AppUtils.isNotNullOrEmpty(request.getAges())) {
			for (Integer age : request.getAges()) {

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);
				
				getDataDashBoardRequest.getAges().add(age);

				graphData.put(String.valueOf(age), getLogiAttemptsStudents(getDataDashBoardRequest));
			}
		} else if (AppUtils.isNotNullOrEmpty(request.getEthnicity())) {

			for (String ethnicity : request.getEthnicity()) {

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);
				
				getDataDashBoardRequest.getEthnicity().add(ethnicity);

				graphData.put(ethnicity, getLogiAttemptsStudents(getDataDashBoardRequest));
			}
		} else if (AppUtils.isNotNullOrEmpty(request.getGradeIds())) {
			for (Long grade_id : request.getGradeIds()) {
				
				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);

				getDataDashBoardRequest.getGradeIds().add(grade_id);

				graphData.put(gradeRepository.getOne(grade_id).getGrade_name(),
						getLogiAttemptsStudents(getDataDashBoardRequest));
			}
		} else if (AppUtils.isNotNullOrEmpty(request.getClassIds())) {
			for (Long class_id : request.getClassIds()) {

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);
				
				getDataDashBoardRequest.getClassIds().add(class_id);

				
				
				graphData.put(classRepository.getOne(class_id).getClass_name(),
						getLogiAttemptsStudents(getDataDashBoardRequest));
			}
		}

		return graphData;
	} */
	
	public LinkedList<LabelAndValue> getLogiAttemptsStudents(GetDataDashBoardRequest request){
		
		List<Activity> activities = activityService.getAllStudentActivitiesByActivityType(request,1L);
		LinkedHashMap<String, List<Activity>> activitiesMap = activityService.getActivityMapByTimeLine(request.getTimeLine(), activities);
		
		LinkedList<LabelAndValue> graphData = new LinkedList<LabelAndValue>();
		
		for (String key : activitiesMap.keySet()) {
			
			LinkedHashSet<Long> ids = new LinkedHashSet<Long>();
			
			List<Activity> values = activitiesMap.get(key);
			
			for(int i = 0; i< values.size(); i++) {
				ids.add(values.get(i).getStudent().getStudent_id());
			}
			
			graphData.add(new LabelAndValue(key, ids.size()));
		}
		
		return graphData;
	}
	
	@Override
	public LinkedHashMap<String, List<LabelAndValue>> getLogiAttemptsTeachersData(GetDataDashBoardRequest request) {
		
		LinkedHashMap<String, List<LabelAndValue>> graphData = new LinkedHashMap<String, List<LabelAndValue>>();

		if (AppUtils.isNotNullOrEmpty(request.getGradeIds())) {
			for (Long grade_id : request.getGradeIds()) {
				
				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);

				getDataDashBoardRequest.getGradeIds().add(grade_id);

				graphData.put(gradeRepository.getOne(grade_id).getGrade_name(),
						getLogiAttemptsTeachers(getDataDashBoardRequest));
			}
		} 

		return graphData;
	}
	
	public LinkedList<LabelAndValue> getLogiAttemptsTeachers(GetDataDashBoardRequest request){
		
		List<Activity> activities = activityService.getAllInstructorActivitiesByActivityType(request,1L);
		LinkedHashMap<String, List<Activity>> activitiesMap = activityService.getActivityMapByTimeLine(request.getTimeLine(), activities);
		
		LinkedList<LabelAndValue> graphData = new LinkedList<LabelAndValue>();
		
		for (String key : activitiesMap.keySet()) {
			
			LinkedHashSet<Long> ids = new LinkedHashSet<Long>();
			
			List<Activity> values = activitiesMap.get(key);
			
			for(int i = 0; i< values.size(); i++) {
				ids.add(values.get(i).getInstructor().getInstructor_id());
			}
			
			graphData.add(new LabelAndValue(key, ids.size()));
		}
		
		return graphData;
	}
	
	@Override
	public LinkedHashMap<String, LinkedHashMap<String, LinkedList<Object>>> getAverageLoginAttemptTeachers(GetDataDashBoardRequest request) {
		
		System.out.println("------------------------------User Stats's Average Login Attempts - Teachers --------------------------------");
		
		List<Instructor> instructors = instructorRepository.findAllOrderById();
		
		System.out.println("Instructors - " + instructors.size());
		
		Date fromDate = AppUtils.isNullOrEmpty(instructors) ? DateUtils.setTimeToFromDate(new Date()) : accountRepository.findByAccountId(instructors.get(0).getAccount_id()).getCreatedAt();
		Date toDate = DateUtils.setTimeToToDate(new Date()); //accountRepository.findByAccountId(instructors.get(instructors.size() - 1).getAccount_id()).getCreatedAt();
		
		LinkedHashMap<String, LinkedHashMap<String, LinkedList<Object>>> graphData = new LinkedHashMap<String, LinkedHashMap<String, LinkedList<Object>>>();
		
		System.out.println("----------------------------- Grade ------------------------------");
		
		if (AppUtils.isNotNullOrEmpty(request.getGradeIds())) {
			
			LinkedHashMap<String, LinkedList<Object>> grades = new LinkedHashMap<String, LinkedList<Object>>();
			
			for (Long grade_id : request.getGradeIds()) {
				
				System.out.println("-----------------------------" + grade_id +"------------------------------");


				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
						request);
				
				getDataDashBoardRequest.getGradeIds().add(grade_id);

				grades.put(gradeRepository.getOne(grade_id).getGrade_name(), getAverageLoginAttemptTeachers(getDataDashBoardRequest, fromDate, toDate));
			}
			
			graphData.put("Grade", grades);
			
		} 
		
				
		return graphData;
	}
	
	public LinkedList<Object> getAverageLoginAttemptTeachers(GetDataDashBoardRequest request, Date fromDate, Date toDate) {

		List<Activity> activities = activityService.getAllInstructorActivitiesByActivityType(request, 1L);

		LinkedList<Object> reportings = new LinkedList<>();

		if(AppUtils.isNotNullOrEmpty(activities)) {
			
			Double size = (double) activities.size();
			
			System.out.println("Instructor List Size - " + size + " FromDate - " + DateUtils.dailyDateFormat.format(fromDate) + " ToDate - " + DateUtils.dailyDateFormat.format(toDate));
			
			System.out.println("----------------------------Daily---------------------------------");
			
			Double days = (double) DateUtils.getDayCountByFromDateAndToDate(fromDate, toDate);
			
			BigDecimal dailyReporting = DigitUtils.getAverageBigDecimal(size, days); 

			System.out.println("dailyReporting - " +  dailyReporting + " = Size: " + size + " / Days: " + days);
			
			reportings.add(dailyReporting); //
			
			System.out.println("----------------------------Weekly---------------------------------");
			
			Double weeks = (double) DateUtils.getWeekCountByFromDateAndToDate(fromDate, toDate);
			
			BigDecimal weeklyReporting = DigitUtils.getAverageBigDecimal(size, weeks); 
						
			System.out.println("weeklyReporting - " +  weeklyReporting + " = Size: " + size + " / Weeks: " + weeks);
			
			reportings.add(weeklyReporting);
			
			System.out.println("----------------------------Monthly---------------------------------");
			
			Double months = (double) DateUtils.getMonthCountByFromDateAndToDate(fromDate, toDate);
			
			BigDecimal monthlyReporting = DigitUtils.getAverageBigDecimal(size, months); 
			
			System.out.println("monthlyReporting - " +  monthlyReporting + " = Size: " + size + " / Months: " + months);
			
			reportings.add(monthlyReporting);
			
			System.out.println("----------------------------Yearly---------------------------------");
			
			Double years = (double) DateUtils.getYearCountByFromDateAndToDate(fromDate, toDate);
			
			BigDecimal yearlyReporting = DigitUtils.getAverageBigDecimal(size, years); 
						
			System.out.println("yearlyReporting - " +  yearlyReporting + " = Size: " + size + " / Years: " + years);
			
			reportings.add(yearlyReporting);

		} else {
			
			reportings.add(DigitUtils.formateZeroToBigDecimal());
			reportings.add(DigitUtils.formateZeroToBigDecimal());
			reportings.add(DigitUtils.formateZeroToBigDecimal());
			reportings.add(DigitUtils.formateZeroToBigDecimal());
		}
		
		return reportings;
	}
	
	@Override
	public LinkedHashMap<String, LinkedList<Object>> getPercentageByGrades(GetDataDashBoardRequest request) {

		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();
		
		Double totalCount = 0.0;

		for (int i = 0; i < request.getGradeIds().size(); i++) {

			Long grade_id = request.getGradeIds().get(i);

			GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(
					request);
			
			getDataDashBoardRequest.getGradeIds().add(grade_id);
			
			long count = activityService.getAllInstructorActivitiesByActivityType(getDataDashBoardRequest, 1L).size();

			totalCount = totalCount + count;

			LinkedList<Object> list = new LinkedList<Object>();
			list.add(count);
			list.add(0);

			countAndAvgMap.put(gradeRepository.getOne(grade_id).getGrade_name(), list);
		}

		DigitUtils.addTotalInMapBigDecimal(countAndAvgMap, totalCount);
		
		return countAndAvgMap;
	}
	
	
	
	private GetDataDashBoardRequest getGetDataDashBoardRequestWithReqeuest(
			GetDataDashBoardRequest request) {
		GetDataDashBoardRequest getDataDashBoardRequest = new GetDataDashBoardRequest();
		getDataDashBoardRequest.setTimeLine(request.getTimeLine());
		getDataDashBoardRequest
				.setSocio_emotional_test_question_type_id(request.getSocio_emotional_test_question_type_id());
		getDataDashBoardRequest.setGraphType(request.getGraphType());
		getDataDashBoardRequest.setFromDate(request.getFromDate());
		getDataDashBoardRequest.setToDate(request.getToDate());
		return getDataDashBoardRequest;
	}

	@Override
	public LinkedHashMap<String, LinkedList<Object>> getPercentageByOSForStudent(GetDataDashBoardRequest request) {
		
		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();
		
		List<Object[]> studentsCountAndPercentageByOS = studentRepository.getStudentCountAndPercentageByUseOfOS();

		for (int i = 0; i < studentsCountAndPercentageByOS.size(); i++) {
			
			Object[] studentCountAndPercentageByOS = studentsCountAndPercentageByOS.get(i);
			
			LinkedList<Object> list = new LinkedList<Object>();
			list.add(studentCountAndPercentageByOS[1]);
			list.add(studentCountAndPercentageByOS[2]);

			countAndAvgMap.put(studentCountAndPercentageByOS[0].toString(), list);
		}
		
		return countAndAvgMap;
	}

	@Override
	public LinkedHashMap<String, LinkedList<Object>> getPercentageByBrowserForStudent(GetDataDashBoardRequest request) {
		
		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();
		
		List<Object[]> studentsCountAndPercentageByBrowser = studentRepository.getStudentCountAndPercentageByUseOfBrowser();

		for (int i = 0; i < studentsCountAndPercentageByBrowser.size(); i++) {
			
			Object[] studentCountAndPercentageByBrowser = studentsCountAndPercentageByBrowser.get(i);
			
			LinkedList<Object> list = new LinkedList<Object>();
			list.add(studentCountAndPercentageByBrowser[1]);
			list.add(studentCountAndPercentageByBrowser[2]);

			countAndAvgMap.put(studentCountAndPercentageByBrowser[0].toString(), list);
		}
		
		return countAndAvgMap;

	}

	@Override
	public LinkedHashMap<String, LinkedList<Object>> getPercentageByOSForInstructor(GetDataDashBoardRequest request) {
		
		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();
		
		List<Object[]> instructorsCountAndPercentageByOS = instructorRepository.getInstructorCountAndPercentageByUseOfOS();

		for (int i = 0; i < instructorsCountAndPercentageByOS.size(); i++) {
			
			Object[] instructorCountAndPercentageByOS = instructorsCountAndPercentageByOS.get(i);
			
			LinkedList<Object> list = new LinkedList<Object>();
			list.add(instructorCountAndPercentageByOS[1]);
			list.add(instructorCountAndPercentageByOS[2]);

			countAndAvgMap.put(instructorCountAndPercentageByOS[0].toString(), list);
		}
		
		return countAndAvgMap;
	}

	@Override
	public LinkedHashMap<String, LinkedList<Object>> getPercentageByBrowserForInstructor(
			GetDataDashBoardRequest request) {
		
		LinkedHashMap<String, LinkedList<Object>> countAndAvgMap = new LinkedHashMap<String, LinkedList<Object>>();
		
		List<Object[]> instructorsCountAndPercentageByBrowser = studentRepository.getStudentCountAndPercentageByUseOfOS();

		for (int i = 0; i < instructorsCountAndPercentageByBrowser.size(); i++) {
			
			Object[] instructorCountAndPercentageByBrowser = instructorsCountAndPercentageByBrowser.get(i);
			
			LinkedList<Object> list = new LinkedList<Object>();
			list.add(instructorCountAndPercentageByBrowser[1]);
			list.add(instructorCountAndPercentageByBrowser[2]);

			countAndAvgMap.put(instructorCountAndPercentageByBrowser[0].toString(), list);
		}
		
		return countAndAvgMap;
	}
}
