package com.infinite.focus.server;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.sql.DataSource;

import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.CacheControl;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.infinite.focus.server.auth.AccessCode;
import com.infinite.focus.server.auth.AccessCodeRepository;
import com.infinite.focus.server.auth.Account;
import com.infinite.focus.server.auth.AccountRepository;
import com.infinite.focus.server.grade.Grade;
import com.infinite.focus.server.grade.GradeRepository;
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.students.Class;
import com.infinite.focus.server.students.StudentClassWrapper;
import com.infinite.focus.server.tests.Question;
import com.infinite.focus.server.tests.QuestionRepository;
import com.infinite.focus.server.tests.SocioEmotionalTestQuestion;
import com.infinite.focus.server.tests.SocioEmotionalTestQuestionRepository;
import com.infinite.focus.server.tests.SocioEmotionalTestQuestionType;
import com.infinite.focus.server.tests.SocioEmotionalTestQuestionTypeRepository;
import com.infinite.focus.server.utils.DateUtils;

@ComponentScan(basePackages = {
		"com.infinite.focus.server.activity", 
		"com.infinite.focus.server.data", 
		"com.infinite.focus.server.grade",
		"com.infinite.focus.server.dashboard",
		"com.infinite.focus.server.tests",
		"com.infinite.focus.server.lessons",
		"com.infinite.focus.server.notifications",
		"com.infinite.focus.server.students", 
		"com.infinite.focus.server.standard", 
		"com.infinite.focus.server.auth", 
		"com.infinite.focus.server.wall",
		"com.infinite.focus.server.home", 
		"com.infinite.focus.server.categories",
		"com.infinite.focus.server.encryptdecrypthelper",
		"com.infinite.focus.server.contents",
		"com.infinite.focus.server.moods",
		"com.infinite.focus.server.resourcelibrary",
		"com.infinite.focus.server.vimeo",
		"com.infinite.focus.server.fcm",
		"com.infinite.focus.server.fcm.service",
		"com.infinite.focus.server.fcm.model", 
		"com.infinite.focus.server.googleapis", 
		"com.infinite.focus.server.googleapis.services", 
		"com.infinite.focus.server.googleapis.youtube", 
		"com.infinite.focus.server.instructor",
		"com.infinite.focus.server.payment",
		"com.infinite.focus.server.about",
		"com.infinite.focus.server.utils" })
@EnableScheduling
@SpringBootApplication
@EnableAsync
public class InfiniteFocusApplication implements WebMvcConfigurer {

	public static void main(String[] args) {
		SpringApplication.run(InfiniteFocusApplication.class, args);
	}

	@Bean
	public BCryptPasswordEncoder bCryptPasswordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	ApplicationRunner applicationRunner(AccountRepository accountRepository, StudentRepository studentRepository, AccessCodeRepository accessCodeRepository,
			InstructorRepository instructorRepository, GradeRepository gradeRepository,
			SocioEmotionalTestQuestionRepository socioEmotionalTestQuestionRepository,
			SocioEmotionalTestQuestionTypeRepository socioEmotionalTestQuestionTypeRepository) {
		return args -> {
			
			/*Calendar c = Calendar.getInstance();
			c.add(Calendar.YEAR, -3);
			// Account's created at
			for (Account a : accountRepository.findAll()) {
				if (a.getCreatedAt() == null) {
					Date startDate = c.getTime();
					c.add(Calendar.DATE, +3);
					Date endDate = c.getTime();
					a.setCreatedAt(DateUtils.between(startDate,endDate));
					accountRepository.save(a);
				}
			}*/
			
			// Student's status AccessCode
			for (Student s : studentRepository.findAll()) {
				if (s.getInstructor_id() > 0 && s.getStatus() == null) {
					Instructor i = instructorRepository.findByInstructorId(s.getInstructor_id());
					AccessCode acce = accessCodeRepository.findByStudentIdAndInstructorId(s.getStudent_id(), i.getInstructor_id());
					if(acce == null) {
						AccessCode accessCode = new AccessCode(s, i);
						accessCodeRepository.save(accessCode);
					}
				}
				
				/*if(s.getDate_of_birth() == null) {
					long date = generateRandomNumberByTwoNumber(1, 25);
			        long month = generateRandomNumberByTwoNumber(0, 11);
			        long year = generateRandomNumberByTwoNumber(2002, 2017);
			        
			        // create a calendar
			        Calendar cal = Calendar.getInstance();

			        // print current time
			        System.out.println("Current year is :" + cal.getTime());

			        // set the year,month and day to something else
			        cal.set((int) year, (int) month, (int)date);
					s.setDate_of_birth(new java.sql.Date(cal.getTime().getTime()));
					studentRepository.save(s);
				}*/
			}

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

			if (grades.isEmpty()) {

				Grade gradeElementary = new Grade();
				gradeElementary.setGrade_name("Elementary");
				gradeRepository.save(gradeElementary);

				Grade gradeMiddle = new Grade();
				gradeMiddle.setGrade_name("Middle");
				gradeRepository.save(gradeMiddle);

				Grade gradeHighSchool = new Grade();
				gradeHighSchool.setGrade_name("High School");
				gradeRepository.save(gradeHighSchool);
			}

			List<SocioEmotionalTestQuestionType> socioEmotionalTestQuestionTypes = socioEmotionalTestQuestionTypeRepository
					.findAll();

			if (socioEmotionalTestQuestionTypes.isEmpty()) {

				/*
				 * Responsible decision making: (questions: 1,5,9) Social Awareness: (questions:
				 * 2, 6, 10) Self-Management: (questions: 3, 7, 11) Relationship Skills:
				 * (questions: 4, 8, 12)
				 * 
				 * question_type_id (PK) - 1 question_type_label - Responsible Decision Making
				 * 
				 * question_type_id (PK) - 2 question_type_label - Social Awareness
				 * 
				 * question_type_id (PK) - 3 question_type_label: Self-management
				 * 
				 * question_type_id (PK) - 4 question_type_label: Relationship Skills
				 */

				SocioEmotionalTestQuestionType socioEmotionalTestQuestionType1 = new SocioEmotionalTestQuestionType();
				socioEmotionalTestQuestionType1.setText("Responsible decision making");
				socioEmotionalTestQuestionTypeRepository.save(socioEmotionalTestQuestionType1);

				SocioEmotionalTestQuestionType socioEmotionalTestQuestionType2 = new SocioEmotionalTestQuestionType();
				socioEmotionalTestQuestionType2.setText("Social Awareness");
				socioEmotionalTestQuestionTypeRepository.save(socioEmotionalTestQuestionType2);

				SocioEmotionalTestQuestionType socioEmotionalTestQuestionType3 = new SocioEmotionalTestQuestionType();
				socioEmotionalTestQuestionType3.setText("Self-Management");
				socioEmotionalTestQuestionTypeRepository.save(socioEmotionalTestQuestionType3);

				SocioEmotionalTestQuestionType socioEmotionalTestQuestionType4 = new SocioEmotionalTestQuestionType();
				socioEmotionalTestQuestionType4.setText("Relationship Skills");
				socioEmotionalTestQuestionTypeRepository.save(socioEmotionalTestQuestionType4);

				List<SocioEmotionalTestQuestion> socioEmotionalTestQuestions = socioEmotionalTestQuestionRepository
						.findAll();

				for (SocioEmotionalTestQuestion socioEmotionalTestQuestion : socioEmotionalTestQuestions) {

					int socio_emotional_test_question_id = (int) socioEmotionalTestQuestion
							.getSocio_emotional_test_question_id();

					switch (socio_emotional_test_question_id) {
					case 1:
					case 5:
					case 9:
						socioEmotionalTestQuestion.setSocio_emotional_test_question_type(1);
						break;
					case 2:
					case 6:
					case 10:
						socioEmotionalTestQuestion.setSocio_emotional_test_question_type(2);
						break;
					case 3:
					case 7:
					case 11:
						socioEmotionalTestQuestion.setSocio_emotional_test_question_type(3);
						break;
					case 4:
					case 8:
					case 12:
						socioEmotionalTestQuestion.setSocio_emotional_test_question_type(4);
						break;

					}

					socioEmotionalTestQuestionRepository.save(socioEmotionalTestQuestion);
				}
			}
		};
	}

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {

		registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/statics/")
				.setCacheControl(CacheControl.maxAge(2, TimeUnit.HOURS).cachePublic());
	}
	
	 static long generateRandomNumberByTwoNumber(int n1, int n2){
         
	        double Random;

	        if (n1 != n2)
	        {
	            if (n1 > n2)
	            {
	                Random = n2 + (Math.random() * (n1 - n2));
	                return Math.round(Random);
	            }
	            else
	            {
	                Random = n1 + (Math.random() * (n2 - n1));
	                return Math.round(Random);
	            }
	        } else {
	            System.out.println("Please provide valid Range " +n1+ " " +n2+ " are equal numbers." );
	        }     
	        return 1;
	    }
}
