package com.nisum.mytime.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang.time.DateUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.nisum.mytime.controller.DomainController;
import com.nisum.mytime.exception.handler.MyTimeException;
import com.nisum.mytime.model.Account;
import com.nisum.mytime.model.BillingDetails;
import com.nisum.mytime.model.Domains;
import com.nisum.mytime.model.EmpLoginData;
import com.nisum.mytime.model.EmpShiftDetails;
import com.nisum.mytime.model.EmployeeDashboardVO;
import com.nisum.mytime.model.EmployeeRoles;
import com.nisum.mytime.model.Project;
import com.nisum.mytime.model.ProjectTeamMate;
import com.nisum.mytime.repository.AccountRepo;
import com.nisum.mytime.repository.DomainRepo;
import com.nisum.mytime.repository.EmpShiftDetailsRepo;
import com.nisum.mytime.repository.EmployeeRolesRepo;
import com.nisum.mytime.repository.ProjectRepo;
import com.nisum.mytime.repository.ProjectTeamMatesRepo;
import com.nisum.mytime.repository.TeamMatesBillingRepo;
import com.nisum.mytime.utils.MyTeamResultDTO;
import com.nisum.mytime.utils.MyTimeUtils;
import com.nisum.mytime.utils.PdfReportGenerator;

@Service("projectService")
public class ProjectServiceImpl implements ProjectService {

    @Autowired
    private EmployeeRolesRepo employeeRolesRepo;

    @Autowired
    private ProjectRepo projectRepo;
    
    @Autowired
    private ProjectTeamMatesRepo projectTeamMatesRepo;
    
    @Autowired
    private TeamMatesBillingRepo teamMatesBillingRepo;

    @Autowired
    private EmployeeDataService employeeDataBaseService;

    @Autowired
    private PdfReportGenerator pdfReportGenerator;

    @Autowired
    private MongoTemplate mongoTemplate;
    
    @Autowired
    private EmpShiftDetailsRepo empShiftDetailsRepo;

    @Autowired
    private DomainController domainController;

    @Autowired
    private RoleInfoService roleInfoService;

    @Autowired
    private RoleMappingService roleMappingService;

    @Autowired
    private AccountRepo accountRepo;

    @Autowired
    private DomainRepo domainRepo;
    
	@Autowired
	private ProjectService projectService;

    @Override
    public List<EmpLoginData> employeeLoginsBasedOnDate(long id,
            String fromDate, String toDate) throws MyTimeException {
        return employeeDataBaseService.fetchEmployeeLoginsBasedOnDates(id,
                fromDate, toDate);
    }

    @Override
    public String generatePdfReport(long id, String fromDate, String toDate)
            throws MyTimeException {
        return pdfReportGenerator.generateEmployeeReport(id, fromDate, toDate);
    }

    @Override
    public List<HashMap<Object, Object>> getProjects() throws MyTimeException {
        /*
         * MT-79:returns all project info. This will get implemented once
         * managers are maintained as List and not attributes return
         * projectRepo.findAll();
         */
        List<HashMap<Object, Object>> projectList = new ArrayList<>();
        List<HashMap<String, String>> EmployeeList = null;
        List<HashMap<String, String>> managerList = null;
        List<Project> projects = projectRepo.findAll();
        for (Project p : projects) {
            HashMap<Object, Object> projectMap = new HashMap<>();
            projectMap.put("id", p.getId());
            projectMap.put("projectId", p.getProjectId());
            projectMap.put("projectName", p.getProjectName());
            Account account = accountRepo.findByAccountId(p.getAccountId());
            Domains domain = domainRepo.findByDomainId(p.getDomainId());
            if (domain != null)
                projectMap.put("domain", domain.getDomainName());
            if (account != null)
                projectMap.put("account", account.getAccountName());
            projectMap.put("accountId", p.getAccountId());
            projectMap.put("domainId", p.getDomainId());
            projectMap.put("status", p.getStatus());
            projectMap.put("employeeIds", p.getEmployeeIds());
            projectMap.put("projectStartDate", p.getProjectStartDate());
            projectMap.put("projectEndDate", p.getProjectEndDate());
            // projectMap.put("deliveryLeadIds", p.getDeliveryLeadIds());

            /*
             * if (p.getManagerIds() == null && p.getManagerId() != null) {
             * EmployeeList = getEmployeeData(Arrays.asList(p.getManagerId()));
             * } else
             */ if (p.getDeliveryLeadIds() != null) {

                List<String> deliverLeadsId = p.getDeliveryLeadIds();
                EmployeeList = getEmployeeData(deliverLeadsId);
                projectMap.put("deliveryLeadIds", EmployeeList);
            }
            if (p.getManagerIds() != null) {

                List<String> managerid = p.getManagerIds();
                managerList = getEmployeeData(managerid);
                projectMap.put("managerIds", managerList);
            }
            projectList.add(projectMap);
        }
        return projectList;
    }

    @Override
    public Project addProject(Project project) throws  MyTimeException {
        if (project.getDomainId() == null) {
            Domains domain = new Domains();
            domain.setAccountId(project.getAccountId());
            domain.setDomainName(project.getDomain());
            domain.setDeliveryManagers(project.getManagerIds());
            domain.setStatus(project.getStatus());
            domainController.addDomain(domain);
            List<Domains> domainsList = domainRepo
                    .findByAccountId(project.getAccountId());
            Domains savedDomain = domainsList.get(0);
            project.setDomainId(savedDomain.getDomainId());
            project.setDomain(savedDomain.getDomainName());
        }
    
        return projectRepo.save(project);
    }

    @Override
    public EmployeeRoles getEmployeesRole(String emailId) {
        return employeeRolesRepo.findByEmailId(emailId);

    }

    @Override
    public void deleteProject(String projectId) {
        Project project = projectRepo.findByProjectId(projectId);
        projectRepo.delete(project);
        Query query = new Query(Criteria.where("projectId").is(projectId));
        List<ProjectTeamMate> list = mongoTemplate.find(query,
                ProjectTeamMate.class);
        projectTeamMatesRepo.delete(list);
    }

    @Override
    public Project updateProject(Project project) throws  MyTimeException {   	
    	//Inactivate the Project based on endDate
		Project existingProject = projectRepo.findByProjectId(project.getProjectId());
		List<ProjectTeamMate> existingTeammates = projectTeamMatesRepo.findByProjectId(project.getProjectId());

		if (project.getProjectEndDate().compareTo(new Date()) <= 0
				&& project.getProjectEndDate().compareTo(existingProject.getProjectEndDate()) != 0) {

			existingProject.setStatus(MyTimeUtils.IN_ACTIVE);
			existingProject.setProjectEndDate(project.getProjectEndDate());
			projectRepo.save(existingProject);
			for (ProjectTeamMate existingTeammate : existingTeammates) {
				existingTeammate.setActive(false);
				existingTeammate.setEndDate(project.getProjectEndDate());

				BillingDetails billingDetails = new BillingDetails();
				billingDetails.setBillableStatus(MyTimeUtils.BENCH_BILLABILITY_STATUS);
				List<BillingDetails> listBD = getEmployeeActiveBillingDetails(existingTeammate.getEmployeeId(),
						existingTeammate.getProjectId());
				if (listBD != null && !listBD.isEmpty()) {
					BillingDetails billingDetailsExisting = listBD.get(0);
					billingDetailsExisting.setBillingEndDate(project.getProjectEndDate());
					billingDetailsExisting.setActive(false);
					updateEmployeeBilling(billingDetailsExisting);
				}
				Date sd = project.getProjectEndDate();
				billingDetails.setBillingStartDate(sd);
				billingDetails.setAccount(MyTimeUtils.BENCH_ACCOUNT);
				billingDetails.setActive(true);
				billingDetails.setEmployeeId(existingTeammate.getEmployeeId());
				billingDetails.setEmployeeName(existingTeammate.getEmployeeName());
				billingDetails.setCreateDate(new Date());
				billingDetails.setProjectId(MyTimeUtils.BENCH_PROJECT_ID);
				billingDetails.setProjectName(MyTimeUtils.FREE_POLL);
				addEmployeeBillingDetails(billingDetails);

				projectTeamMatesRepo.save(existingTeammate);
				ProjectTeamMate newBenchAllocation = new ProjectTeamMate();
				Project benchProject = projectRepo.findByProjectId(MyTimeUtils.BENCH_PROJECT_ID);
				if (benchProject != null)
					newBenchAllocation.setAccountId(benchProject.getAccountId());
				newBenchAllocation.setBillableStatus(MyTimeUtils.BENCH_BILLABILITY_STATUS);
				newBenchAllocation.setDesignation(existingTeammate.getDesignation());
				newBenchAllocation.setEmailId(existingTeammate.getEmailId());
				newBenchAllocation.setEmployeeId(existingTeammate.getEmployeeId());
				newBenchAllocation.setActive(true);
				newBenchAllocation.setEmployeeName(existingTeammate.getEmployeeName());
				newBenchAllocation.setProjectId(MyTimeUtils.BENCH_PROJECT_ID);
				newBenchAllocation.setStartDate(sd);
				newBenchAllocation.setProjectName(benchProject.getProjectName());
				projectTeamMatesRepo.save(newBenchAllocation);
				 updateShiftDetails(existingTeammate);
			}
			return existingProject;

		}
		else
	   {
        Query query = new Query(
                Criteria.where("projectId").is(project.getProjectId()));
        Update update = new Update();
        update.set("projectName", project.getProjectName());
        if (project.getDeliveryLeadIds() != null) {
            update.set("deliveryLeadIds", project.getDeliveryLeadIds());
        }
        /*
         * if(project.getManagerIds()!= null) { update.set("managerIds",
         * project.getManagerIds()); }
         *//*
            * else{
            * update.set("managerIds",Arrays.asList(project.getManagerId())); }
            */
        update.set("domain", project.getDomain());
        update.set("domainId", project.getDomainId());
        update.set("accountId", project.getAccountId());
        update.set("status", project.getStatus());
        update.set("projectStartDate", project.getProjectStartDate());
        update.set("projectEndDate", project.getProjectEndDate());
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);
        options.upsert(true);
        Project projectDB = mongoTemplate.findAndModify(query, update, options,
                Project.class);
        List<ProjectTeamMate> employeeDetails = projectTeamMatesRepo
                .findByProjectId(project.getProjectId());
        if (employeeDetails != null && projectDB != null) {
            for (ProjectTeamMate emp : employeeDetails) {
                // emp.setManagerId(projectDB.getManagerId());
                // emp.setManagerName(projectDB.getManagerName());
                emp.setAccountId(projectDB.getAccountId());
                emp.setProjectName(projectDB.getProjectName());
                // MT-79:Maintatin the managerids in List
                // emp.setManagerIds(projectDB.getManagerIds());
                emp.setEndDate(projectDB.getProjectEndDate());
                projectTeamMatesRepo.save(emp);
            }
        }
        return projectDB;
	   }
    }

    @Override
    public EmployeeRoles getEmployeesRoleData(String employeeId) {
        return employeeRolesRepo.findByEmployeeId(employeeId);
    }

    @Override
    public List<ProjectTeamMate> getTeamDetails(String empId) {
        List<String> projectsId = new ArrayList<>();
        List<ProjectTeamMate> listOfTeamMates = new ArrayList<>();
        // return projectTeamMatesRepo.findById(empId);
        // Query query = new Query(Criteria.where("deliveryLeadIds").("empId"));

        List<Project> projects = projectRepo.findByDeliveryLeadIds(empId);// mongoTemplate.find(query,
                                                                          // Project.class);
        for (Project project : projects)
            projectsId.add(project.getProjectId());
        Query query1 = new Query(Criteria.where("projectId").in(projectsId));
        List<ProjectTeamMate> projectMateList = mongoTemplate.find(query1,
                ProjectTeamMate.class);
        for (ProjectTeamMate projectTeamMate : projectMateList) {
            if (!projectTeamMate.getEmployeeId().equals(empId))
                listOfTeamMates.add(projectTeamMate);
        }
        return listOfTeamMates;

    }

    // MT-72: fetching the projectteammate details.
    @Override
    public List<ProjectTeamMate> getProjectInfo(String employeeId) {
        return mongoTemplate.find(getQuery(employeeId, MyTimeUtils.START_DATE),
                ProjectTeamMate.class);
    }

    @Override
    public ProjectTeamMate addProjectTeamMate(ProjectTeamMate projectTeamMate) throws MyTimeException {
        updateProjectEndDateInProjectTeamMate(projectTeamMate);
        ProjectTeamMate pT = projectTeamMatesRepo.save(projectTeamMate);
        List<BillingDetails> listBD = getEmployeeActiveNisumBench(pT.getEmployeeId());
        Date startDate = pT.getStartDate() != null ? pT.getStartDate() : new Date();
        if (listBD != null && listBD.size() >0) {
        	BillingDetails bDetails = listBD.get(0);
            if (startDate.compareTo(bDetails.getBillingStartDate()) > 0) {
            	bDetails.setBillingEndDate(DateUtils.truncate(DateUtils.addDays(startDate, -1), Calendar.DATE));
            } else {
            	bDetails.setBillingEndDate(startDate);
            }
            bDetails.setActive(false);
            updateEmployeeBilling(bDetails);
        }
        BillingDetails billings = new BillingDetails();
        billings.setEmployeeId(pT.getEmployeeId());
        billings.setEmployeeName(pT.getEmployeeName());
        billings.setProjectId(pT.getProjectId());
        billings.setProjectName(pT.getProjectName());
        billings.setBillableStatus(pT.getBillableStatus());
        billings.setAccount(pT.getAccount());
        billings.setActive(pT.isActive());
        if (!projectTeamMate.getProjectId().equalsIgnoreCase("Nisum0000")) {
        	billings.setBillingStartDate(DateUtils.truncate(pT.getNewBillingStartDate(), Calendar.DATE));
        } else {
        	billings.setBillingStartDate(DateUtils.truncate(pT.getStartDate(), Calendar.DATE));
        }
        if (pT.getEndDate() != null) {
            billings.setBillingEndDate(DateUtils.truncate(pT.getEndDate(), Calendar.DATE));
        }
        billings.setCreateDate(new Date());
        //updateProjectEndDateInBillingDetails(projectTeamMate.getNewBillingStartDate(), billings);
        addEmployeeBillingDetails(billings);
        addShiftDetails(projectTeamMate);
        /*if (projectTeamMate.getProjectId() != null && !projectTeamMate.getProjectId().equalsIgnoreCase("Nisum0000")) {
            List<ProjectTeamMate> activeBenchProject = projectTeamMatesRepo
                    .findByEmployeeIdAndProjectIdAndActive(projectTeamMate.getEmployeeId(), "Nisum0000", true);
            if (activeBenchProject != null && activeBenchProject.size() != 0) {
                for (ProjectTeamMate pteamMate : activeBenchProject) {
                    Date d = (pT.getStartDate() != null) ? pT.getStartDate() : new Date();
                    pteamMate.setActive(false);
                    pteamMate.setEndDate(DateUtils.truncate(DateUtils.addDays(d, -1), Calendar.DATE));
                    projectTeamMatesRepo.save(pteamMate);
                }
            }
        }*/
        addOrUpdateTeamMateRole(projectTeamMate.getRole(), projectTeamMate.getProjectId(), projectTeamMate.getEmployeeId(), false);
        return pT;
    }
    
    private void addOrUpdateTeamMateRole(String role, String projectId, String empId, boolean isUpdate) throws MyTimeException {
    	Project project = projectRepo.findByProjectId(projectId);
    	int operationType = 0; //0 = No Operation, 1 = Added, 2 = Removed
        if (role != null && role.equals("Lead")) {
        	if (project.getManagerIds() == null) {
        		project.setManagerIds(Arrays.asList(empId));
        		operationType = 1;
        	} else if (project.getManagerIds() != null && !project.getManagerIds().contains(empId)) {
                project.getManagerIds().add(empId);
                operationType = 1;
            }
        } else if (isUpdate && project.getManagerIds() != null && project.getManagerIds().contains(empId)) {// When role got changed from Lead to Employee.
        	project.getManagerIds().remove(empId);
        	operationType = 2;
        }
        if (operationType > 0) {
        	projectRepo.save(project);
        	Query query = new Query(Criteria.where("employeeId").is(empId).and("role").is("Lead"));
            List<ProjectTeamMate> projectMates = mongoTemplate.find(query, ProjectTeamMate.class);
            String roleId = roleInfoService.getRole(MyTimeUtils.LEAD);
            if (operationType ==1) {
        		roleMappingService.addEmployeeRole(empId, roleId);
        	} else if (projectMates.size() == 0 || operationType == 2) {
        		roleMappingService.deleteRole(empId, roleId);
        	}
        }
    }

    @Override
    public String updateTeammate(ProjectTeamMate projectTeamMate) throws MyTimeException {
    	//String result = null;
    	MyTeamResultDTO myResultDto = new MyTeamResultDTO();
    	myResultDto.setResultCode(MyTeamResultDTO.SUCCESS_CODE);
    	myResultDto.setResultData("TeamMate updated successfuly");
    	ProjectTeamMate existingTeammate = projectTeamMatesRepo.findById(projectTeamMate.getId());
    	List<BillingDetails> listBD = getEmployeeActiveBillingDetails(projectTeamMate.getEmployeeId(), projectTeamMate.getProjectId());
    	Date resEndDate = projectTeamMate.getEndDate();
    	
    	//Handling past or present endDate (To "Inactive" the Resource)
    	if (resEndDate.compareTo(new Date()) <= 0 && resEndDate.compareTo(existingTeammate.getEndDate()) != 0) {
			existingTeammate.setActive(false);
			existingTeammate.setEndDate(resEndDate);
			if (listBD != null && !listBD.isEmpty()) {
				BillingDetails billingDetailsExisting = listBD.get(0);
				Date actualEndDate = resEndDate;
				billingDetailsExisting.setBillingEndDate(actualEndDate);
				billingDetailsExisting.setActive(false);
				updateEmployeeBilling(billingDetailsExisting);
			}
			Project project = projectRepo.findByProjectId(MyTimeUtils.BENCH_PROJECT_ID);
			ProjectTeamMate newBenchAllocation = new ProjectTeamMate();
			BillingDetails billingDetails = new BillingDetails();
			billingDetails.setBillableStatus(MyTimeUtils.BENCH_BILLABILITY_STATUS);
			billingDetails.setBillingStartDate(resEndDate);
			billingDetails.setAccount(MyTimeUtils.BENCH_ACCOUNT);
			billingDetails.setActive(true);
			billingDetails.setEmployeeId(existingTeammate.getEmployeeId());
			billingDetails.setEmployeeName(existingTeammate.getEmployeeName());
			billingDetails.setCreateDate(new Date());
			billingDetails.setProjectId(MyTimeUtils.BENCH_PROJECT_ID);
			billingDetails.setProjectName(MyTimeUtils.FREE_POLL);
			if(project != null) {
				billingDetails.setBillingEndDate(project.getProjectEndDate());
				newBenchAllocation.setAccountId(project.getAccountId());
				newBenchAllocation.setDomainId(project.getDomainId());
				newBenchAllocation.setProjectName(project.getProjectName());
				newBenchAllocation.setEndDate(project.getProjectEndDate());
			}
			addEmployeeBillingDetails(billingDetails);

			newBenchAllocation.setBillableStatus(MyTimeUtils.BENCH_BILLABILITY_STATUS);
			newBenchAllocation.setDesignation(existingTeammate.getDesignation());
			newBenchAllocation.setEmailId(existingTeammate.getEmailId());
			newBenchAllocation.setEmployeeId(existingTeammate.getEmployeeId());
			newBenchAllocation.setActive(true);
			newBenchAllocation.setEmployeeName(existingTeammate.getEmployeeName());
			newBenchAllocation.setProjectId(MyTimeUtils.BENCH_PROJECT_ID);
			newBenchAllocation.setShift(existingTeammate.getShift());
			newBenchAllocation.setRole(existingTeammate.getRole());

			Calendar cal = Calendar.getInstance();
			cal.setTime(resEndDate);
			cal.add(Calendar.DAY_OF_MONTH, 1);

			newBenchAllocation.setStartDate(DateUtils.truncate(cal.getTime(), Calendar.DATE));
			newBenchAllocation.setNewBillingStartDate(DateUtils.truncate(cal.getTime(), Calendar.DATE));

			projectTeamMatesRepo.save(newBenchAllocation);

			myResultDto.setResultCode(MyTeamResultDTO.SUCCESS_CODE);
			myResultDto.setResultData("Resource Successfully moved from " + projectTeamMate.getProjectName() + " project to Bench.");
		} else {
	        //Handling Resource Project Billability Status change
	        if (projectTeamMate.getBillableStatus() != null && existingTeammate.getBillableStatus() != null
						&& !existingTeammate.getBillableStatus().equalsIgnoreCase(projectTeamMate.getBillableStatus())) {
	        	/*List<BillingDetails> bDetailsList = teamMatesBillingRepo.findByEmployeeId(projectTeamMate.getEmployeeId()).stream()
	                    .filter(e -> (!e.isActive())).sorted(Comparator.comparing(BillingDetails::getBillingEndDate).reversed())
	                    .collect(Collectors.toList());*/
				String result = validateBillabilityStartDate(listBD, projectTeamMate);
				if (result != null) { //Invalid Billability Start date
					return result;
				}
				if (listBD != null && !listBD.isEmpty()) {
					BillingDetails billingDetails = listBD.get(0);
					Calendar cal = Calendar.getInstance();
					cal.setTime(projectTeamMate.getNewBillingStartDate());
					cal.add(Calendar.DAY_OF_MONTH, -1);
					if (existingTeammate.getNewBillingStartDate().getDate() == projectTeamMate.getNewBillingStartDate().getDate()) {
						billingDetails.setBillingEndDate(DateUtils.truncate(projectTeamMate.getNewBillingStartDate(), Calendar.DATE));
					} else {
						billingDetails.setBillingEndDate(DateUtils.truncate(cal.getTime(), Calendar.DATE));
					}
					billingDetails.setActive(false);
					updateEmployeeBilling(billingDetails);
				}
				BillingDetails billings = new BillingDetails();
				billings.setEmployeeId(projectTeamMate.getEmployeeId());
				billings.setEmployeeName(projectTeamMate.getEmployeeName());
				billings.setProjectId(projectTeamMate.getProjectId());
				billings.setAccount(existingTeammate.getAccount());
				billings.setProjectName(projectTeamMate.getProjectName());
				billings.setBillableStatus(projectTeamMate.getBillableStatus());
				billings.setActive(true);
				billings.setBillingStartDate(DateUtils.truncate(projectTeamMate.getNewBillingStartDate(), Calendar.DATE));
				billings.setBillingEndDate(DateUtils.truncate(resEndDate, Calendar.DATE));
				billings.setCreateDate(new Date());
				addEmployeeBillingDetails(billings);
				
				existingTeammate.setBillableStatus(projectTeamMate.getBillableStatus());
				existingTeammate.setNewBillingStartDate(DateUtils.truncate(projectTeamMate.getNewBillingStartDate(), Calendar.DATE));
				
			} else {//Handling Billability Start Date change
				List<BillingDetails> bDetailsList = teamMatesBillingRepo.findByEmployeeId(projectTeamMate.getEmployeeId()).stream()
		                .filter(e -> (!e.isActive())).sorted(Comparator.comparing(BillingDetails::getBillingEndDate).reversed())
		                .collect(Collectors.toList());
				String result = validateBillabilityStartDate(bDetailsList, projectTeamMate);
				if (result != null) { //Invalid Billability Start date
					return result;
				}
				if (bDetailsList != null && !bDetailsList.isEmpty()) {
					Calendar cal = Calendar.getInstance();
					cal.setTime(projectTeamMate.getNewBillingStartDate());
					cal.add(Calendar.DAY_OF_MONTH, -1);
					BillingDetails preBillingDetails = bDetailsList.get(0);
					if (preBillingDetails.getBillingStartDate().getDate() == projectTeamMate.getNewBillingStartDate().getDate()) {
						preBillingDetails.setBillingEndDate(DateUtils.truncate(projectTeamMate.getNewBillingStartDate(), Calendar.DATE));
					} else {
						preBillingDetails.setBillingEndDate(DateUtils.truncate(cal.getTime(), Calendar.DATE));
					}
					updateEmployeeBilling(preBillingDetails);
				}
				if (listBD != null && !listBD.isEmpty()) {
					BillingDetails billingDetails = listBD.get(0);
					billingDetails.setBillingStartDate(DateUtils.truncate(projectTeamMate.getNewBillingStartDate(), Calendar.DATE));
					billingDetails.setBillingEndDate(DateUtils.truncate(resEndDate, Calendar.DATE));
					addEmployeeBillingDetails(billingDetails);
				}
				existingTeammate.setNewBillingStartDate(DateUtils.truncate(projectTeamMate.getNewBillingStartDate(), Calendar.DATE));
			}
	        if (resEndDate.compareTo(existingTeammate.getEndDate()) != 0) {
	        	existingTeammate.setEndDate(resEndDate);
	        }
		}
        
		if (MyTeamResultDTO.SUCCESS_CODE.equals(myResultDto.getResultCode())) {
	    	//Handling Role change
	    	if ((existingTeammate.getRole() != null && !existingTeammate.getRole().equalsIgnoreCase(projectTeamMate.getRole()))
	    			|| (projectTeamMate.getRole() != null) && !projectTeamMate.getRole().equalsIgnoreCase(existingTeammate.getRole())) {
	    		existingTeammate.setRole(projectTeamMate.getRole());
	    		addOrUpdateTeamMateRole(projectTeamMate.getRole(), projectTeamMate.getProjectId(), projectTeamMate.getEmployeeId(), true);
	    	}
	    	//Handling Shift change
	    	if ((existingTeammate.getShift() != null && !existingTeammate.getShift().equalsIgnoreCase(projectTeamMate.getShift()))
	    			|| (projectTeamMate.getShift() != null) && !projectTeamMate.getShift().equalsIgnoreCase(existingTeammate.getShift())) {
	    		updateShiftDetails(existingTeammate);
	    		existingTeammate.setShift(projectTeamMate.getShift());
		        EmployeeRoles employeeDB = employeeRolesRepo.findByEmployeeId(projectTeamMate.getEmployeeId());
		        employeeDB.setShift(projectTeamMate.getShift());
		        employeeRolesRepo.save(employeeDB);
	    	}
			projectTeamMatesRepo.save(existingTeammate);
		}
        return myResultDto.getResultData()[myResultDto.getDataArrayCounter()];
    }
	
	private String validateBillabilityStartDate(List<BillingDetails> bDetailsList, ProjectTeamMate projectTeamMate) {
		String response = null;
		if (bDetailsList != null && bDetailsList.size() > 0) {
			BillingDetails bDetails = bDetailsList.get(0);
			if (projectTeamMate.getNewBillingStartDate().compareTo(bDetails.getBillingStartDate()) < 0) {
				response = "Resource Billability Start Date (" + projectTeamMate.getNewBillingStartDate() +" ) for "
					+ projectTeamMate.getBillableStatus() + " status should be later than previous billability ("
					+ bDetails.getBillableStatus() + " status) Start Date ( " + bDetails.getBillingStartDate() + ").";
			}
		} else {
			response = validateAgainstDOJ(projectTeamMate);
		}
		return response;
	}

    public void updateShiftDetails(ProjectTeamMate existingTeammate) {
        Query getQuery = new Query();
        getQuery.addCriteria(new Criteria().andOperator(Criteria.where("active").is(true),
        		Criteria.where("employeeId").is(existingTeammate.getEmployeeId())));
        //Calendar cal = Calendar.getInstance();
        //cal.add(Calendar.DATE, -1);
        EmpShiftDetails existingShift = mongoTemplate.findOne(getQuery, EmpShiftDetails.class);
        if (existingShift != null) {
            existingShift.setActive(false);
            existingShift.setUpdatedDate(new Date());
            mongoTemplate.save(existingShift);
        }
    }

    public void addShiftDetails(ProjectTeamMate projectTeamMate) {
        EmpShiftDetails empShiftDetails = new EmpShiftDetails();
        empShiftDetails.setCreateDate(new Date());
        empShiftDetails.setUpdatedDate(new Date());
        empShiftDetails.setEmployeeName(projectTeamMate.getEmployeeName());
        empShiftDetails.setEmployeeId(projectTeamMate.getEmployeeId());
        empShiftDetails.setShift(projectTeamMate.getShift());
        empShiftDetails.setActive(projectTeamMate.isActive());
        empShiftDetailsRepo.save(empShiftDetails);
    }

    @Override
    public void deleteTeammate(String empId, String projectId, ObjectId id) {
        ProjectTeamMate existingTeammate = projectTeamMatesRepo.findById(id);
        existingTeammate.setActive(false);
        existingTeammate.setEndDate(new Date());
        BillingDetails billingDetails = new BillingDetails();
        billingDetails.setBillableStatus("Non-Billable");
        billingDetails.setBillingStartDate(new Date());
        billingDetails.setAccount("Nisum");
        billingDetails.setActive(true);
        billingDetails.setEmployeeId(existingTeammate.getEmployeeId());
        billingDetails.setEmployeeName(existingTeammate.getEmployeeName());
        billingDetails.setCreateDate(new Date());
        billingDetails.setProjectId("Nisum0000");
        billingDetails.setProjectName(MyTimeUtils.FREE_POLL);
        addEmployeeBillingDetails(billingDetails);
        List<BillingDetails> listBD = getEmployeeActiveBillingDetails(empId,
                projectId);
        if (listBD != null && !listBD.isEmpty()) {
            BillingDetails billingDetailsExisting = listBD.get(0);
            Date d = new Date();
            d.setDate(d.getDate() - 1);
            billingDetailsExisting.setBillingEndDate(d);
            billingDetailsExisting.setActive(false);
            updateEmployeeBilling(billingDetailsExisting);
        }
        projectTeamMatesRepo.save(existingTeammate);
        ProjectTeamMate newBenchAllocation = new ProjectTeamMate();
        newBenchAllocation.setAccount("Nisum");
        newBenchAllocation.setBillableStatus("Non-Billable");
        newBenchAllocation.setDesignation(existingTeammate.getDesignation());
        newBenchAllocation.setEmailId(existingTeammate.getEmailId());
        newBenchAllocation.setEmployeeId(existingTeammate.getEmployeeId());
        newBenchAllocation.setActive(true);
        newBenchAllocation.setEmployeeName(existingTeammate.getEmployeeName());
        newBenchAllocation.setProjectId("Nisum0000");
        newBenchAllocation.setStartDate(new Date());
        Project p = projectRepo.findByProjectId("Nisum0000");
        newBenchAllocation.setProjectName(p.getProjectName());
        // newBenchAllocation.setManagerId(p.getManagerId());
        // newBenchAllocation.setManagerName(p.getManagerName());
        projectTeamMatesRepo.save(newBenchAllocation);
        updateShiftDetails(existingTeammate);
    }

    @Override
    public List<Project> getProjects(String managerId) throws MyTimeException {
        /*
         * Query query = new Query(Criteria.where("managerId").is(managerId)
         * .and("status").ne("Completed")); return mongoTemplate.find(query,
         * Project.class);
         */
        List<Project> projectList = new ArrayList<>();
        List<Project> projects = projectRepo.findByDeliveryLeadIds(managerId);
        for (Project project : projects) {
            if (!project.getStatus().equals("Completed")) {
                projectList.add(project);
            }

        }
        return projectList;
    }

    @Override
    public List<ProjectTeamMate> getMyTeamDetails(String empId) {
        List<ProjectTeamMate> teamMates = new ArrayList<>();
        List<ProjectTeamMate> empRecords = projectTeamMatesRepo
                .findByEmployeeId(empId);
        for (ProjectTeamMate pt : empRecords) {
            if (pt.isActive()) {
                teamMates.addAll(projectTeamMatesRepo
                        .findByProjectId(pt.getProjectId()));
            }
        }
        return teamMates;
    }

    @Override
    public List<EmployeeRoles> getUnAssignedEmployees() {
        List<EmployeeRoles> allEmployees = employeeRolesRepo.findAll();
        List<EmployeeRoles> notAssignedEmployees = new ArrayList<>();
        List<String> teamMates = new ArrayList<>();
        List<ProjectTeamMate> empRecords = projectTeamMatesRepo.findAll();
        for (ProjectTeamMate pt : empRecords) {
            Project project = projectRepo.findByProjectId(pt.getProjectId());
            if (project != null && project.getStatus() != null
                    && !"Completed".equalsIgnoreCase(project.getStatus())) {
                teamMates.add(pt.getEmployeeId());
            }
        }
        for (EmployeeRoles emp : allEmployees) {

            if (!teamMates.contains(emp.getEmployeeId())) {
                notAssignedEmployees.add(emp);
            }
        }

        return notAssignedEmployees;
    }

    @Override
    public List<ProjectTeamMate> getShiftDetails(String shift) {
    	List<ProjectTeamMate> employeeDetails = null;
        List<ProjectTeamMate> shiftEmpDetails = new ArrayList<>();
        List<Project> projects = projectRepo.findAll();
        for (Project pt : projects) {
            if ("Active".equalsIgnoreCase(pt.getStatus())) {
                employeeDetails = projectTeamMatesRepo.findByProjectId(pt.getProjectId());
                for (ProjectTeamMate emp : employeeDetails) {
                    if (emp.getShift() != null && emp.getShift().equalsIgnoreCase(shift) && emp.isActive()) {
                        shiftEmpDetails.add(emp);
                    } else if (emp.getShift() == null && "Shift 1(9:00 AM - 6:00 PM)".equalsIgnoreCase(shift) && emp.isActive())
                        shiftEmpDetails.add(emp);
                }
            }
        }
        return shiftEmpDetails;
    }

    @Override
    public List<ProjectTeamMate> getAllProjectDetails() {
        List<Project> projects = projectRepo.findAll();
        List<ProjectTeamMate> allprojectMates = new ArrayList<>();
        for (Project pt : projects) {
            if (!"Completed".equalsIgnoreCase(pt.getStatus())) {
                List<ProjectTeamMate> employeeDetails = projectTeamMatesRepo
                        .findByProjectId(pt.getProjectId());
                allprojectMates.addAll(employeeDetails);
            }

        }
        return allprojectMates;
    }

    @Override
    public List<ProjectTeamMate> getProjectDetails(String projectId,String statusFlag) {
		List<ProjectTeamMate> teamMatesList = new ArrayList<>();
		List<ProjectTeamMate> teamMates = projectTeamMatesRepo.findByProjectId(projectId);
		for (ProjectTeamMate projectTeamMate : teamMates) {
			Date endDate = projectTeamMate.getEndDate();
			if (endDate != null) { 
				// Active
				if (statusFlag.equals(MyTimeUtils.ACTIVE) && endDate.compareTo(new Date()) >= 0)
					teamMatesList.add(projectTeamMate);
				else if (statusFlag.equals(MyTimeUtils.IN_ACTIVE) && endDate.compareTo(new Date()) < 0)
					teamMatesList.add(projectTeamMate);
				else if (statusFlag.equals(MyTimeUtils.BOTH))
					teamMatesList.add(projectTeamMate);
			}
		}
		return teamMatesList;
    }

    @Override
    public List<ProjectTeamMate> getMyProjectAllocations(String empId) {
        return projectTeamMatesRepo.findByEmployeeId(empId);
    }

    @Override
    public List<BillingDetails> getEmployeeBillingDetails(String empId, String projectId) {
        List<BillingDetails> billings = teamMatesBillingRepo.findByEmployeeIdAndProjectId(empId, projectId);
        List<BillingDetails> billingsSorted = billings;
        try {
            billingsSorted = (billings == null || billings.size() == 0) ? billings : billings.stream().sorted(
            		Comparator.comparing(BillingDetails::getCreateDate).reversed()).collect(Collectors.toList());
        } catch (Exception e) {
            // TODO: handle exception
        }
        return billingsSorted;
    }

    @Override
    public List<BillingDetails> getEmployeeBillingDetailsAll(String empId) {
        List<BillingDetails> billings = teamMatesBillingRepo.findByEmployeeId(empId);
        List<BillingDetails> billingsSorted = billings;
        try {
            billingsSorted = (billings == null || billings.size() == 0) ? billings : billings.stream().sorted(
            		Comparator.comparing(BillingDetails::getCreateDate).reversed()).collect(Collectors.toList());
        } catch (Exception e) {
            // TODO: handle exception
        }
        return billingsSorted;
    }

    @Override
    public List<BillingDetails> getEmployeeActiveBillingDetails(String empId, String projectId) {
        Query query4 = new Query();
        query4.addCriteria(Criteria.where("active").is(new Boolean(true)));
        query4.addCriteria(Criteria.where("employeeId").is(empId));
        query4.addCriteria(Criteria.where("projectId").is(projectId));
        List<BillingDetails> billings = mongoTemplate.find(query4, BillingDetails.class);
        List<BillingDetails> billingsSorted = billings;
        try {
            billingsSorted = (billings == null || billings.size() == 0) ? billings : billings.stream().sorted(
            		Comparator.comparing(BillingDetails::getBillingStartDate).reversed()).collect(Collectors.toList());
        } catch (Exception e) {
            // TODO: handle exception
        }
        return billingsSorted;
    }

    @Override
    public List<BillingDetails> getEmployeeActiveNisumBench(String empId) {
        Query query4 = new Query();
        query4.addCriteria(Criteria.where("active").is(new Boolean(true)));
        query4.addCriteria(Criteria.where("projectId").is("Nisum0000"));
        query4.addCriteria(Criteria.where("employeeId").is(empId));
        List<BillingDetails> billings = mongoTemplate.find(query4, BillingDetails.class);
        List<BillingDetails> billingsSorted = billings;
        try {
            billingsSorted = (billings == null || billings.size() == 0) ? billings : billings.stream().sorted(
            		Comparator.comparing(BillingDetails::getBillingStartDate).reversed()).collect(Collectors.toList());
        } catch (Exception e) {
            // TODO: handle exception
        }
        return billingsSorted;
    }

    @Override
    public BillingDetails addEmployeeBillingDetails(BillingDetails teamMate) {
        /*
         * List<BillingDetails> billingsPast = getEmployeeBillingDetails(
         * teamMate.getEmployeeId(), teamMate.getProjectId());
         */ /*
             * for (BillingDetails tB : billingsPast) { tB.setActive(false);
             * teamMatesBillingRepo.save(tB); }
             */
        return teamMatesBillingRepo.save(teamMate);
    }

    @Override
    public BillingDetails updateEmployeeBilling(BillingDetails teamMate) {
        return teamMatesBillingRepo.save(teamMate);
    }

    // Update ProjectEndDate column data in ProjectTeamMate.
    private void updateProjectEndDateInProjectTeamMate(ProjectTeamMate projectTeamMate) {
        List<ProjectTeamMate> projectTeamMateList = mongoTemplate
                .find(getQuery(projectTeamMate.getEmployeeId(), MyTimeUtils.ENDDATE_COLUMN), ProjectTeamMate.class);
        if (!CollectionUtils.isEmpty(projectTeamMateList)) {
        	ProjectTeamMate teamMate = projectTeamMateList.get(0);
        	Date d = projectTeamMate.getNewBillingStartDate();
			Calendar cal = Calendar.getInstance();
			cal.setTime(d);
			cal.add(Calendar.DAY_OF_MONTH, -1);
			Date oneDayLess = cal.getTime();

			if (teamMate.getNewBillingStartDate().getDate() == projectTeamMate.getNewBillingStartDate().getDate()) {
				teamMate.setEndDate(DateUtils.truncate(projectTeamMate.getEndDate(), Calendar.DATE));
			} else {
				teamMate.setEndDate(DateUtils.truncate(oneDayLess, Calendar.DATE));
			}
			teamMate.setActive(false);
			projectTeamMatesRepo.save(teamMate);
        }

    }

/*    // Update BillingEndDate in BillingDetails.
    private void updateProjectEndDateInBillingDetails(Date newBillingStartDate, BillingDetails billingDetails) {
        List<BillingDetails> billingDetailsList = mongoTemplate.find(
        		getQuery(billingDetails.getEmployeeId(), MyTimeUtils.CREATED_DATE_COLUMN), BillingDetails.class);
        if (!CollectionUtils.isEmpty(billingDetailsList)) {
        	BillingDetails billing = billingDetailsList.get(0);
        	Date d = billingDetails.getBillingStartDate();
			Calendar cal = Calendar.getInstance();
			cal.setTime(d);
			cal.add(Calendar.DAY_OF_MONTH, -1);
			Date oneDayLess = cal.getTime();

			if (billing.getBillingStartDate().getDate() == billingDetails.getBillingStartDate().getDate()) {
				billing.setBillingEndDate(DateUtils.truncate(billingDetails.getBillingEndDate(), Calendar.DATE));
			} else {
				billing.setBillingEndDate(DateUtils.truncate(oneDayLess, Calendar.DATE));
			}
			teamMatesBillingRepo.save(billing);
        }
    }

    // Update ProjectEndDate
    private void updateProjectEndDate(Date newBillingStartDate, String employeeId, String projectName,String dateColumn,
    		String collectionName) {
        DBCollection collection = mongoTemplate.getCollection(collectionName);
        BasicDBObject searchQuery = new BasicDBObject();
        searchQuery.append(MyTimeUtils.EMPLOYEE_ID, employeeId);
        searchQuery.append(MyTimeUtils.PROJECT_NAME, projectName);
        BasicDBObject updateQuery = new BasicDBObject();
        updateQuery.append(MyTimeUtils.SET, new BasicDBObject().append(dateColumn,DateUtils.addDays(
        		newBillingStartDate, MyTimeUtils.MINUS_ONE)));
        collection.update(searchQuery, updateQuery);
    }*/

    private Query getQuery(String employeeId, String dateColumn) {
        Query query = new Query();
        query.addCriteria(Criteria.where(MyTimeUtils.EMPLOYEE_ID).is(employeeId));
        query.limit(MyTimeUtils.ONE);
        query.with(new Sort(Sort.Direction.DESC, dateColumn));
        return query;
    }

    @Override
    public void deleteEmployeeBilling(BillingDetails teamMate) {
        teamMatesBillingRepo.delete(teamMate);
    }

    @Override
    public List<EmployeeDashboardVO> getEmployeesDashBoard() {
        List<EmployeeRoles> allEmployees = employeeRolesRepo.findAll();
        List<EmployeeRoles> notAssignedEmployees = new ArrayList<>();
        List<EmployeeDashboardVO> employeeDashboard = new ArrayList<>();
        Map<String, Object> teamMatesMap = new HashMap();
        Map<String, Object> teamMatesStatusMap = new HashMap();

        // Find all active employees
        List<ProjectTeamMate> empRecords = projectTeamMatesRepo.findAll();
        for (ProjectTeamMate pt : empRecords) {
            if (pt.isActive()) {
                Project project = projectRepo
                        .findByProjectId(pt.getProjectId());
                if (project != null && project.getStatus() != null
                        && !"Completed".equalsIgnoreCase(project.getStatus())) {
                    Object projectTeamMate = teamMatesMap
                            .get(pt.getEmployeeId());

                    if (projectTeamMate == null) {
                        List listOfObjects = new ArrayList<>();
                        listOfObjects.add(pt);
                        // A person can have multiple active projects with billability
                        teamMatesMap.put(pt.getEmployeeId(), listOfObjects);
                    } else {
                        List existingRecordsInMap = (List) teamMatesMap
                                .get(pt.getEmployeeId());
                        existingRecordsInMap.add(pt);
                        teamMatesMap.put(pt.getEmployeeId(),
                                existingRecordsInMap);

                    }
                }
            }
        }
        for (EmployeeRoles emp : allEmployees) {
            if (emp.getEmployeeId() != null
                    && emp.getEmployeeId().equalsIgnoreCase("16112")) {
                System.out.println(emp);
            }

            if (teamMatesMap.containsKey(emp.getEmployeeId())) {
                System.out.println("***************** Empl alrady assigned");
                Object value = teamMatesMap.get(emp.getEmployeeId());
                if (value instanceof List) {
                    List listOfTeamMates = (List) value;
                    String billableStatus = "NA";

                    for (Object obj : listOfTeamMates) {
                        ProjectTeamMate projectTeamMate = (ProjectTeamMate) obj;
                        String status = projectTeamMate.getBillableStatus();
                        if (status == null) {
                            status = "NA";
                        }
                        System.out.println("---------------------------");
                        EmployeeDashboardVO empVo = new EmployeeDashboardVO();

                        System.out.println(emp);
                        BeanUtils.copyProperties(emp, empVo);
                        BeanUtils.copyProperties(projectTeamMate, empVo,
                                "employeeId", "employeeName", "emailId", "role",
                                "designation", "mobileNumber");

                        employeeDashboard.add(empVo);
                    }

                }
            } else {
                EmployeeDashboardVO empVo = new EmployeeDashboardVO();

                System.out.println(emp);
                BeanUtils.copyProperties(emp, empVo);
                empVo.setBillableStatus("UA");
                empVo.setProjectAssigned(false);
                employeeDashboard.add(empVo);
            }
            System.out.println("&&&&&&&&&&");
            // System.out.println(empVo);

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

        }

        return employeeDashboard;
    }

    @Override
    public List<ProjectTeamMate> findByAccountAndActiveAndBillableStatus(
            String account, boolean status, String billableStatus) {
        return projectTeamMatesRepo.findByAccountAndActiveAndBillableStatus(
                account, status, billableStatus);
    }

    public List<HashMap<String, String>> getEmployeeData(List<String> ids) {
        List<HashMap<String, String>> EmployeeList = new ArrayList<>();

        Query query = new Query(Criteria.where("employeeId").in(ids));
        List<EmployeeRoles> employeeRoles = mongoTemplate.find(query,
                EmployeeRoles.class);
        for (EmployeeRoles employeesRole : employeeRoles) {
            HashMap<String, String> managerMap = new HashMap<>();
            managerMap.put("employeeId", employeesRole.getEmployeeId());
            managerMap.put("employeeName", employeesRole.getEmployeeName());
            EmployeeList.add(managerMap);
        }
        return EmployeeList;
    }
    
	@Override
	public String addProjectTeamMateWithCheck(ProjectTeamMate projectTeamMate) throws MyTimeException {
		boolean flag = false;
		String projectName = null;
		String fromDate = null;
		String toDate = null;
		String result = null;
		List<ProjectTeamMate> teamMateList = projectTeamMatesRepo.findByEmployeeId(projectTeamMate.getEmployeeId()).stream()
                .filter(e -> !("Nisum0000".equalsIgnoreCase(e.getProjectId())))
                .sorted(Comparator.comparing(ProjectTeamMate::getEndDate).reversed())
                .collect(Collectors.toList());
		// Checking, if resource has existing project assignment.
		for (ProjectTeamMate projectMate : teamMateList) {
			if (projectMate.getEndDate() != null && (projectMate.getEndDate().compareTo(new Date()) > 0)) {
				flag = true;
				projectName = projectMate.getProjectName();
				fromDate = projectMate.getStartDate().toString();
				toDate = projectMate.getEndDate().toString();
				break;
			}
		}
		if (flag) {// If yes, error thrown to user.
			result = "Resource " + projectTeamMate.getEmployeeId() + " already Assigned to the " + projectName
					+ " Project" + " from " + fromDate + "to " + toDate;
		} else {// If no, validating new project assignment start date against previous project end date.
			result = validateNewProjectAssignmentStartDate(teamMateList, projectTeamMate);
			if (result == null) {
				addProjectTeamMate(projectTeamMate);
				result = "TeamMate added successfuly";
			}
		}
		return result;

	}
	
	private String validateNewProjectAssignmentStartDate(List<ProjectTeamMate> teamMateList, ProjectTeamMate projectTeamMate) {
		String response = null;
		if (teamMateList != null && teamMateList.size() > 0) {
			ProjectTeamMate ptMate = teamMateList.get(0);
			if (projectTeamMate.getNewBillingStartDate().compareTo(ptMate.getEndDate()) <= 0) {
				response = "Resource Start Date (" + projectTeamMate.getNewBillingStartDate() +" ) in " + projectTeamMate.getProjectName()
				+ " project should be after " + ptMate.getProjectName() + " project End Date ( " + ptMate.getEndDate() + ").";
			}
		} else {
			response = validateAgainstDOJ(projectTeamMate);
		}
		return response;
	}
	
	private String validateAgainstDOJ(ProjectTeamMate projectTeamMate) {
		String response = null;
		Date empDoj = employeeRolesRepo.findByEmployeeId(projectTeamMate.getEmployeeId()).getDateOfJoining();
		if(projectTeamMate.getNewBillingStartDate().compareTo(empDoj) < 0) {
			response = "Resource Start Date (" + projectTeamMate.getNewBillingStartDate() +" ) in " + projectTeamMate.getProjectName()
			+ " project should not be before Date of Joining ( " + empDoj + ").";
		}
		return response;
	}
	
	@Override
	public List<HashMap<Object, Object>>  projectsInfoByEmpId(String empId){
		HashMap<Object, Object> projectMap =null;
		List<HashMap<Object, Object>> projectList = new ArrayList<>();
		 
		Project project= null;
		Account account = null;
		Domains domain = null;
		
		List<ProjectTeamMate> projectAllocations = getMyProjectAllocations(empId);
		
		if( null != projectAllocations && !projectAllocations.isEmpty() && MyTimeUtils.INT_ZERO < projectAllocations.size()) {
			for (ProjectTeamMate ptm : projectAllocations) {
				projectMap = new HashMap<>();
				
				project = projectRepo.findByProjectId(ptm.getProjectId());
				
				account = accountRepo.findByAccountId(ptm.getAccountId());
		        domain = domainRepo.findByDomainId(ptm.getDomainId());
		        
		        projectMap.put("id", project.getId());
				projectMap.put("projectId", project.getProjectId());
			    projectMap.put("projectName", project.getProjectName());
			    
			    if (domain != null) 
			    	projectMap.put("domain", domain.getDomainName());
			   
			    if (account != null)
	                projectMap.put("account", account.getAccountName());
			    
			    projectMap.put("accountId", account!=null?account.getAccountId():ptm.getAccountId());
			    projectMap.put("domainId",  domain!=null? domain.getDomainId() : ptm.getDomainId() );
			    projectMap.put("status", ptm.isActive());
			    projectMap.put("projectStartDate",ptm.getStartDate());
			    projectMap.put("projectEndDate",ptm.getEndDate());
	            projectMap.put("employeeIds", ptm.getEmployeeId());
	            projectMap.put("shift", ptm.getShift());
	            projectMap.put("billableStatus", ptm.getBillableStatus());    
	            
	            if (project.getDeliveryLeadIds() != null) {
	            	projectMap.put("deliveryLeadIds", getEmployeeData(project.getDeliveryLeadIds()));
	            }
	            
	            if (project.getManagerIds() != null) {
	                projectMap.put("managerIds", getEmployeeData(project.getManagerIds()));
	            }
	            
	            projectList.add(projectMap);
			} 
		}	
		return projectList;
	}

	@Override
	public Set<String> accountsAssignedToDl(String empId) {
		Set<String> accIdsSet = new HashSet<String>() ;
		
		List<Project> prjtsList = projectRepo.findByDeliveryLeadIds(empId);
		
		if(null != prjtsList && !prjtsList.isEmpty() && MyTimeUtils.INT_ZERO < prjtsList.size()) {
			for(Project obj : prjtsList) {
				accIdsSet.add(obj.getAccountId());				
			}
		}
		return accIdsSet;
	}
	
	
	   @Override
   public List<HashMap<Object, Object>> deliveryLeadProjects(String empId) throws MyTimeException {
	   List<HashMap<Object, Object>> projectsList = new ArrayList<HashMap<Object, Object>> ();
			
		Set<String> accIdsSet = projectService.accountsAssignedToDl(empId);
		List<Project> prjts= projectRepo.findByAccountIdIn(accIdsSet);		

		if(null != prjts && !prjts.isEmpty() && MyTimeUtils.INT_ZERO < prjts.size()) {
			Account account = null;
			Domains domain =null;

			HashMap<Object, Object> projectMap = null;

			for(Project obj : prjts) {
				projectMap = new HashMap<>();
				
				account = accountRepo.findByAccountId(obj.getAccountId());
				domain = domainRepo.findByDomainId(obj.getDomainId());
					
				projectMap.put("projectId", obj.getProjectId());
				projectMap.put("projectName",obj.getProjectName());
					
				projectMap.put("accountId", obj.getAccountId());
				projectMap.put("domainId", obj.getDomainId());
				
				projectMap.put("account", null != account ? account.getAccountName():"");
				projectMap.put("domain", null != domain ? domain.getDomainName() : "");
				projectMap.put("status", obj.getStatus());
				
					
				projectMap.put("deliveryLeadIds", null != obj.getDeliveryLeadIds() ? getEmployeeData(obj.getDeliveryLeadIds()) : "");
				projectMap.put("managerIds", null != obj.getManagerIds() ?  getEmployeeData(obj.getManagerIds()) : "");
									
				projectsList.add(projectMap);
			}
		}		   
		return projectsList;
   }
}
