package com.jasamedika.medifirst2000.interceptor;

import java.lang.reflect.Method;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.jasamedika.medifirst2000.constants.Constants;
import com.jasamedika.medifirst2000.dao.LoginUserDao;
import com.jasamedika.medifirst2000.dao.MapLoginUserToRuanganDao;
import com.jasamedika.medifirst2000.dao.MapObjekModulToKelompokUserDao;
import com.jasamedika.medifirst2000.entities.KelompokUser;
import com.jasamedika.medifirst2000.entities.LoginUser;
import com.jasamedika.medifirst2000.entities.MapObjekModulToKelompokUser;
import com.jasamedika.medifirst2000.security.model.AppPermission;
import com.jasamedika.medifirst2000.security.service.TokenAuthenticationService;

/**
 * Interceptor class for All annotation method controller @AppPermission
 * 
 * @author Roberto
 */
public class AppInterceptor implements HandlerInterceptor {
	
	private final Logger LOG = LoggerFactory.getLogger(AppInterceptor.class);
	
	@Autowired
	private TokenAuthenticationService tokenAuthenticationService;
	
	@Autowired
	private LoginUserDao loginUserDao;
	
	@Autowired
	private MapObjekModulToKelompokUserDao mapObjekModulToKelompokUserDao;
	
//	@Autowired
//	private MapLoginUserToRuanganDao mapLoginUserToRuanganDao;
	
	public AppInterceptor() {}
	
	/*
	 * return true untuk valid permission request ke controller method
	 * */
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		try {
			HandlerMethod hm = (HandlerMethod) handler;
			Method method = hm.getMethod();
			
			if (method.isAnnotationPresent(AppPermission.class)) {/*
				String moduleName = request.getHeader(Constants.HttpHeader.MODULE) == null ? "" : request.getHeader(Constants.HttpHeader.MODULE);
				String formName = request.getHeader(Constants.HttpHeader.FORM) == null ? "" : request.getHeader(Constants.HttpHeader.FORM);
				String action = request.getHeader(Constants.HttpHeader.ACTION) == null ? "" : request.getHeader(Constants.HttpHeader.ACTION);
				
				String methodName = method.getAnnotation(AppPermission.class)
						.value();
				Authentication authentication = tokenAuthenticationService
						.getAuthentication(request);
				String namaUser = authentication.getName();
				List<LoginUser> loginUser = loginUserDao.findByNamaUser(namaUser);
				if (loginUser.isEmpty()) {
					// untuk testing false
//					response.addHeader("Access-Control-Expose-Headers", "content-type");
					response.setHeader(Constants.MessageInfo.ERROR_MESSAGE, "User "
							+ namaUser + " can not access Controller " + methodName);
					response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
					return false;
				}
				
				// get user login
				if (!loginUser.isEmpty()) {
					LoginUser user = loginUser.get(0);
					
					// get application modules
					KelompokUser role = user.getKelompokUser();
					boolean result = false;
					if (role != null) {
						List<MapObjekModulToKelompokUser> objekModules = mapObjekModulToKelompokUserDao.findByKelompokUser(role.getId());
						if (!objekModules.isEmpty()) {
							// matching current module to user's module
							for (MapObjekModulToKelompokUser module : objekModules) {
								if (moduleName.equals(module.getReportDisplay())) {
									LOG.info("Module match");
									
									// matching user's action
									switch (action.toLowerCase()) {
									case "save":
									case "simpan":
										if (module.getSimpan())
											result = true;
										break;
									case "edit":
									case "ubah":
										if (module.getEdit())
											result = true;
										break;
									case "print":
									case "cetak":
										if (module.getCetak())
											result = true;
										break;
									case "delete":
									case "hapus":
										if (module.getHapus())
											result = true;
										break;
									}
									
									break;
								}
							}
							
							
							if (result) {
								response.setStatus(HttpServletResponse.SC_OK);
								response.setHeader(Constants.MessageInfo.INFO_MESSAGE, "Supervise execution success");
								return true;
							} else {
								response.addHeader("RequireSupervisor", "true");
								response.setStatus(HttpServletResponse.SC_FORBIDDEN);
								response.setHeader(Constants.MessageInfo.ERROR_MESSAGE, "Action requires supervisor");
								return false;
							}
							
						} else {
							LOG.info("User {} has no access to module application");
							response.setStatus(HttpServletResponse.SC_FORBIDDEN);
							response.setHeader(Constants.MessageInfo.ERROR_MESSAGE, "User has no access to module application");
							return false;
						}
						
					} else {
						LOG.info("User {} has no role to gain access restricted area", namaUser);
						response.setStatus(HttpServletResponse.SC_FORBIDDEN);
						response.setHeader(Constants.MessageInfo.ERROR_MESSAGE, "User has no role to gain access restricted area");
						return false;
					}
				} else {
					LOG.info("User {} is unauthorized", namaUser);
					response.setStatus(HttpServletResponse.SC_FORBIDDEN);
					response.setHeader(Constants.MessageInfo.ERROR_MESSAGE, "User is unauthorized");
					return false;
				}
			*/
				
			return true;
					
			}
		} catch (Exception e) {
			System.out.println("Not Found "+request.getRequestURL());
		}
		return true;
	}

	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object obj, Exception ex)
			throws Exception {
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response,
			Object obj, ModelAndView mav) throws Exception {
	}

}