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

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.EntityManager;

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

import com.infinite.focus.server.activity.Activity;
import com.infinite.focus.server.activity.ActivityRepository;
import com.infinite.focus.server.activity.screen.ScreenRepository;
import com.infinite.focus.server.activity.service.ActivityService;
import com.infinite.focus.server.auth.AccountRepository;
import com.infinite.focus.server.auth.InstructorRepository;
import com.infinite.focus.server.auth.StudentRepository;
import com.infinite.focus.server.dashboard.DashboardController;
import com.infinite.focus.server.dashboard.GetDataDashBoardRequest;
import com.infinite.focus.server.data.MoodOccurance;
import com.infinite.focus.server.grade.GradeRepository;
import com.infinite.focus.server.home.MoodUpdate;
import com.infinite.focus.server.standard.StandardRepository;
import com.infinite.focus.server.students.ClassRepository;
import com.infinite.focus.server.students.service.StudentService;
import com.infinite.focus.server.utils.AppUtils;
import com.infinite.focus.server.utils.TimeUtils;

@Service
public class FeaturesServiceImpl implements FeaturesService {

	@Autowired
	EntityManager entityManager;

	@Autowired
	AccountRepository accountRepository;

	@Autowired
	GradeRepository gradeRepository;

	@Autowired
	StandardRepository standardRepository;

	@Autowired
	StudentRepository studentRepository;

	@Autowired
	InstructorRepository instructorRepository;

	@Autowired
	ClassRepository classRepository;

	@Autowired
	ActivityRepository activityRepository;
	
	@Autowired
	ActivityService activityService;

	@Autowired
	StudentService studentService;

	@Autowired
	ScreenRepository screenRepository;

	String forwardSlash = "/";

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

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

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

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

			LinkedHashMap<String, LinkedList<String>> genderMap = new LinkedHashMap<String, LinkedList<String>>();

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

				System.out.println("-----------------------------" + gender + "------------------------------");

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(request);

				getDataDashBoardRequest.getGenders().add(gender);

				genderMap.put(gender, getFeatureAndTimeMostAndLeast(activityService.getAllStudentActivitiesByActivityType(getDataDashBoardRequest, 3L)));
			}

			graphData.put("Gender", genderMap);

		}

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

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

			LinkedHashMap<String, LinkedList<String>> ageMap = new LinkedHashMap<String, LinkedList<String>>();

			for (Integer age : request.getAges()) {

				System.out.println("-----------------------------" + age + "------------------------------");

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(request);

				getDataDashBoardRequest.getAges().add(age);

				ageMap.put(String.valueOf(age), getFeatureAndTimeMostAndLeast(activityService.getAllStudentActivitiesByActivityType(getDataDashBoardRequest, 3L)));
			}

			graphData.put("Age", ageMap);

		}

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

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

			LinkedHashMap<String, LinkedList<String>> ethnicityMap = new LinkedHashMap<String, LinkedList<String>>();

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

				System.out.println("-----------------------------" + ethnicity + "------------------------------");

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(request);

				getDataDashBoardRequest.getEthnicity().add(ethnicity);

				ethnicityMap.put(ethnicity, getFeatureAndTimeMostAndLeast(activityService.getAllStudentActivitiesByActivityType(getDataDashBoardRequest, 3L)));
			}

			graphData.put("Ethnicity", ethnicityMap);

		}

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

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

			LinkedHashMap<String, LinkedList<String>> gradeMap = new LinkedHashMap<String, LinkedList<String>>();

			for (Long grade_id : request.getGradeIds()) {

				System.out.println("-----------------------------" + grade_id + "------------------------------");

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(request);

				getDataDashBoardRequest.getGradeIds().add(grade_id);

				gradeMap.put(gradeRepository.getOne(grade_id).getGrade_name(),
						getFeatureAndTimeMostAndLeast(activityService.getAllStudentActivitiesByActivityType(getDataDashBoardRequest, 3L)));
			}

			graphData.put("Grade", gradeMap);

		}

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

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

			LinkedHashMap<String, LinkedList<String>> classroomMap = new LinkedHashMap<String, LinkedList<String>>();

			for (Long class_id : request.getClassIds()) {

				System.out.println("-----------------------------" + class_id + "------------------------------");

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(request);

				getDataDashBoardRequest.getClassIds().add(class_id);

				classroomMap.put(DashboardController.getClassNameWithInstructorFullName(class_id, classRepository, instructorRepository),
						getFeatureAndTimeMostAndLeast(activityService.getAllStudentActivitiesByActivityType(getDataDashBoardRequest, 3L)));
			}

			graphData.put("Classroom", classroomMap);

		}

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

		GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(request);
		LinkedHashMap<String, LinkedList<String>> overall = new LinkedHashMap<String, LinkedList<String>>();
		overall.put("Overall", getFeatureAndTimeMostAndLeast(activityService.getAllStudentActivitiesByActivityType(getDataDashBoardRequest, 3L)));
		graphData.put("Overall", overall);

		return graphData;
	}

	public LinkedList<String> getFeatureAndTimeMostAndLeast(List<Activity> activities) {

		LinkedHashMap<Long, Long> featuresMap = new LinkedHashMap<Long, Long>();

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

			Activity activity = activities.get(i);

			long key = activity.getEntity_id();
			long differnce = (activity.getEnd_date_time().getTime() - activity.getStart_date_time().getTime());

			if (featuresMap.containsKey(key)) {
				long appUsedTime = differnce + featuresMap.get(key);
				featuresMap.put(key, appUsedTime);
			} else {
				featuresMap.put(key, differnce);
			}
		}

		LinkedList<FeatureAndTime> featureAndTimeList = new LinkedList<FeatureAndTime>();

		for (Long key : featuresMap.keySet()) {
			FeatureAndTime featureAndTime = new FeatureAndTime();
			featureAndTime.setFeature(screenRepository.getOne(key).getName());
			featureAndTime.setTime(featuresMap.get(key));
			featureAndTimeList.add(featureAndTime);
		}

		Collections.sort(featureAndTimeList, new Comparator<FeatureAndTime>() {
			@Override
			public int compare(FeatureAndTime u1, FeatureAndTime u2) {

				Long count1 = u1.getTime();
				Long count2 = u2.getTime();

				return count2.compareTo(count1);
			}
		});

		LinkedList<String> mostAndLeast = new LinkedList<>();

		if(AppUtils.isNotNullOrEmpty(featureAndTimeList)) {
			FeatureAndTime most = featureAndTimeList.get(0);
			FeatureAndTime least = featureAndTimeList.get(featureAndTimeList.size() - 1);

			mostAndLeast.add(most.getFeature() + " (" + TimeUtils.getTimeInString(most.getTime()) + ")");
			mostAndLeast.add(least.getFeature() + " (" + TimeUtils.getTimeInString(least.getTime()) + ")");
		} else {
			mostAndLeast.add("");
			mostAndLeast.add("");
		}
	
		return mostAndLeast;
	}
	
	@Override
	public LinkedHashMap<String, LinkedHashMap<String, LinkedList<String>>> getByTeachersGradesData(
			GetDataDashBoardRequest request) {

		LinkedHashMap<String, LinkedHashMap<String, LinkedList<String>>> graphData = new LinkedHashMap<String, LinkedHashMap<String, LinkedList<String>>>();
		
		System.out.println("----------------------------- Grade ------------------------------");

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

			LinkedHashMap<String, LinkedList<String>> gradeMap = new LinkedHashMap<String, LinkedList<String>>();

			for (Long grade_id : request.getGradeIds()) {

				System.out.println("-----------------------------" + grade_id + "------------------------------");

				GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(request);

				getDataDashBoardRequest.getGradeIds().add(grade_id);

				gradeMap.put(gradeRepository.getOne(grade_id).getGrade_name(),
						getFeatureAndTimeMostAndLeast(activityService.getAllInstructorActivitiesByActivityType(getDataDashBoardRequest, 3L)));
			}

			graphData.put("Grade", gradeMap);

		}

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

		GetDataDashBoardRequest getDataDashBoardRequest = getGetDataDashBoardRequestWithReqeuest(request);
		LinkedHashMap<String, LinkedList<String>> overall = new LinkedHashMap<String, LinkedList<String>>();
		overall.put("Overall", getFeatureAndTimeMostAndLeast(activityService.getAllInstructorActivitiesByActivityType(getDataDashBoardRequest, 3L)));
		graphData.put("Overall", overall);

		return graphData;
	}

	
	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 LinkedList<PageAndPerformance> getPagePerformanceAnalyticsOrderByScreenId() {
		
		List<Object[]> pageAndPerformanceResult = activityRepository.getPagePerformanceAnalyticsOrderByScreenId();
		
		LinkedList<PageAndPerformance> pageAndPerformanceList = new LinkedList<>();
		
		for(Object[] item: pageAndPerformanceResult) {
			PageAndPerformance pageAndPerformance = new PageAndPerformance();
			pageAndPerformance.setPage_name(item[1]);
			pageAndPerformance.setViews(item[2]);
			pageAndPerformance.setAvg_time(item[5]);
			pageAndPerformanceList.add(pageAndPerformance);
		}
		
		return pageAndPerformanceList;
	}
}
