package com.nisum.mytime.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
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.StringUtils;

import com.mongodb.WriteResult;
import com.nisum.mytime.exception.handler.MyTimeException;
import com.nisum.mytime.model.Domains;
import com.nisum.mytime.model.EmployeeRoles;
import com.nisum.mytime.repository.DomainRepo;

import com.nisum.mytime.utils.MyTimeUtils;


/**
 * @author Vijay
 *
 */
@Service
public class DomainServiceImpl implements DomainService {
	
	List<Domains> domainList = null;
	List<HashMap<Object, Object>> updatedDomainList = null;
	List<HashMap<String, String>> updatedEmployeeList = null;

    @Autowired
    private DomainRepo domainRepo;
    
    @Autowired
	private MongoTemplate mongoTemplate;
    
    @Autowired
   	private RoleInfoService roleInfoService;
    
    @Autowired
    private RoleMappingService roleMappingService;
   
    
    @Override
	public String addDomains(Domains d) throws MyTimeException {
        String response=null;
        List<Domains> domainList=domainRepo.findByDomainNameAndAccountName(d.getDomainName(),d.getAccountName());
       
        if(domainList.size()>0) {
            response="Domain already exists";
            return response;
        }
        
        if (StringUtils.isEmpty(d.getDomainId()) && d.getId()==null) {
            d.setDomainId((MyTimeUtils.DOM + MyTimeUtils.ZERO_) + (getAllDomains().size() +1));
        }
        d.setStatus(MyTimeUtils.ACTIVE);
        
        if(d.getId()==null){
            response="Domain saved succesfully";
        }else{
            response="Domain updated succesfully";
        }
        domainRepo.save(d);
        String roleId = roleInfoService.getRole(MyTimeUtils.DOMAIN);
        roleMappingService.saveUniqueEmployeeAndRole(d.getDeliveryManagers(), roleId);
        return response;
	}
    
    @Override
    public List<HashMap<Object, Object>> getAllDomains() throws MyTimeException {

    	domainList=domainRepo.findAll();
    	updatedDomainList = new ArrayList<>();
		for (Domains domain : domainList) {
			HashMap<Object, Object> domainMap = new HashMap<>();
			domainMap.put(MyTimeUtils.ID,domain.getId());
			domainMap.put(MyTimeUtils.DOMAIN_ID, domain.getDomainId());
			domainMap.put(MyTimeUtils.DOMAIN_NAME,domain.getDomainName());
			domainMap.put(MyTimeUtils.ACCOUNT_NAME,domain.getAccountName());
			domainMap.put(MyTimeUtils.STATUS,domain.getStatus());

			updatedEmployeeList = new ArrayList<>();
			List<String> employeeIds=domain.getDeliveryManagers();

			Query query = new Query(Criteria.where(MyTimeUtils.EMPLOYEE_ID).in(employeeIds));
			List<EmployeeRoles> employeeRoles = mongoTemplate.find(query, EmployeeRoles.class);

			for(EmployeeRoles employeesRole : employeeRoles){
				HashMap<String, String> employeeMap = new HashMap<>();	
				employeeMap.put(MyTimeUtils.EMPLOYEE_ID,employeesRole.getEmployeeId());
				employeeMap.put(MyTimeUtils.EMPLOYEE_NAME,employeesRole.getEmployeeName());
				updatedEmployeeList.add(employeeMap);
			}	
			domainMap.put(MyTimeUtils.DELIVERY_MANAGERS,updatedEmployeeList);
			updatedDomainList.add(domainMap);
		}
    	return updatedDomainList;
    }
    
    @Override
	public String updateDomain(Domains d) throws MyTimeException{
		 String response=null;
		List<String> domEmpIds=new ArrayList<String>();
		List<String> updatedEmpIds=new ArrayList<String>();
		domainList=domainRepo.findAll();
		String roleId = roleInfoService.getRole(MyTimeUtils.DOMAIN);
		for (Domains domain : domainList) {
			List<String> employeeIds=domain.getDeliveryManagers();
			for(String eIds:employeeIds)
				domEmpIds.add(eIds);
		}
		d.setStatus(MyTimeUtils.ACTIVE);
		domainRepo.save(d);
		Query selectedDomainQuery = new Query(Criteria.where(MyTimeUtils.DOMAIN_ID).in(d.getDomainId()).and(MyTimeUtils.STATUS).in(MyTimeUtils.ACTIVE) );
		List<Domains> selectedDomain = mongoTemplate.find(selectedDomainQuery, Domains.class);
		for (String empId : selectedDomain.get(0).getDeliveryManagers()) {
			   int occurrences = Collections.frequency(domEmpIds, empId);
			 if(occurrences==0) {
					//roleMappingService.saveUniqueEmployeeAndRole(empId, roleId);
				 updatedEmpIds.add(empId);
			   }
		} 
		roleMappingService.saveUniqueEmployeeAndRole(updatedEmpIds, roleId);  
		return response;
	}
    
    @Override
    public WriteResult deleteDomain(String id) throws MyTimeException{
        List<String> domEmpIds=new ArrayList<String>();
        String roleId = roleInfoService.getRole(MyTimeUtils.DOMAIN);
        domainList=domainRepo.findAll();
        Query selectedDomainQuery = new Query(Criteria.where(MyTimeUtils.DOMAIN_ID).in(id).and(MyTimeUtils.STATUS).in(MyTimeUtils.ACTIVE) );
        List<Domains> selectedDomain = mongoTemplate.find(selectedDomainQuery, Domains.class);
        
        for (Domains domain : domainList) {
            List<String> employeeIds=domain.getDeliveryManagers();
            for(String eIds:employeeIds)
                domEmpIds.add(eIds);
        }
        
        for (String empId : selectedDomain.get(0).getDeliveryManagers()) {
               int occurrences = Collections.frequency(domEmpIds, empId);
               if(occurrences==1) {
                   //Service call for RoleMapping 
                   roleMappingService.deleteRole(empId,roleId);
               }
        } 
        Update update = new Update();
    	update.set(MyTimeUtils.STATUS,MyTimeUtils.IN_ACTIVE);
    	return mongoTemplate.upsert(selectedDomainQuery, update,Domains.class);
    }
}