package cokr.xit.fims.base.web;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import cokr.xit.applib.AppCmmnUtil;
import cokr.xit.base.code.CommonCode;
import cokr.xit.base.code.service.CodeService;
import cokr.xit.base.security.access.service.AuthorityService;
import cokr.xit.base.user.SigunguQuery;
import cokr.xit.base.user.service.SigunguDepartmentService;
import cokr.xit.base.user.service.UserService;
import cokr.xit.fims.FimsConf;
import cokr.xit.fims.base.FimsUser;
import cokr.xit.fims.base.service.bean.OgdpBean;
import cokr.xit.fims.base.service.bean.SseBean;
import cokr.xit.fims.task.TaskRequestMappingHandlerMapping;
import cokr.xit.foundation.data.DataObject;
import cokr.xit.foundation.web.RequestHandlerReader;

@Controller
public class MainController extends cokr.xit.base.web.MainController {
	@Autowired
	private TaskRequestMappingHandlerMapping requestHandlers;
	@Autowired
	private SseBean sseBean;
	@Resource(name="ogdpBean")
	private OgdpBean ogdpBean;
	@Resource(name="userService")
	private UserService userService;
	@Resource(name="sigunguDepartmentService")
	private SigunguDepartmentService sggDeptService;
	@Resource(name="codeService")
	private CodeService codeService;
	@Resource(name="authorityService")
	private AuthorityService authorityService;

	@Override
	public ModelAndView loginPage() {
		List<DataObject> sggs = sggDeptService.getSigunguList(new SigunguQuery());
		if (sggs.isEmpty())
			throw new RuntimeException("No sigungu info found.");

		for(DataObject sgg : sggs) {
			int count = ogdpBean.countUser(sgg.string("SGG_CD"));
			String userUseYn = count > 0 ? "Y" : "N";
			sgg.set("USER_USE_YN", userUseYn);
		}

		return new ModelAndView("login")
			.addObject("sggs", toJson(sggs))
			.addObject("multipleSggs", sggs.size() > 1)
			.addObject("sggList", sggs)
        	.addObject("sysSggCd", System.getProperty("sgg"));
	}

	@Override
	public ModelAndView getURLs(boolean multiple) {
		List<DataObject> urls = new RequestHandlerReader().read(requestHandlers);
		attachTaskPrefixName(urls);

		return new ModelAndView("select-url")
			.addObject("multiple", multiple)
			.addObject("urls", toJson(urls));
	}

	@SuppressWarnings("unchecked")
	private void attachTaskPrefixName(List<DataObject> urlTree) {
		List<String> tasks = FimsConf.get().getTasks();
		tasks.forEach(task -> task = "/" + task);

		List<String> taskUrlNames = FimsConf.get().getTaskUrlNames();

		for(DataObject item : urlTree) {
			String urlname = item.string("name");
			String url = item.string("url");
			if(!urlname.equals(url)) {
				for(int i=0; i<tasks.size();i++) {
					if(url.startsWith("/"+tasks.get(i))) {
						item.set("name",taskUrlNames.get(i)+" "+urlname);
					}
				}
			}
			if(item.get("children") != null) {
				attachTaskPrefixName((List<DataObject>) item.get("children"));
			}
		}
	}

	@GetMapping(name="회원가입 페이지", value="/signupPage.do")
	public ModelAndView signupPage(String sggCd, String cntnSeCd) {
		ModelAndView mav = new ModelAndView("fims/user/user01010-main")
			.addObject("userInfo", "{}");

		if(cntnSeCd.equals("01")) {
			mav.addObject("cntnSeCd", "01")
			   .addObject("allOgdpList", ogdpBean.selectAllOgdpList());
			List<DataObject> ableOgdpList =  ogdpBean.selectAbleOgdpList(true, sggCd);
			mav.addObject("ableOgdpList", ableOgdpList);

			Map<String, List<CommonCode>> commonCodes = codeService.getCodesOf("CMN008");
			mav.addObject("CMN008List", commonCodes.get("CMN008"));
		} else if(cntnSeCd.equals("02")) {
			List<DataObject> sggs = sggDeptService.getSigunguList(new SigunguQuery().setSggIDs(sggCd));

			mav.addObject("cntnSeCd", "02")
			   .addObject("sggCd", sggCd)
			   .addObject("institute", sggs.get(0).string("INST_CD"))
			   .addObject("userSeCd", "21");
		}

		return mav;
	}

	@RequestMapping(name="회원가입", value="/signup.do")
	public ModelAndView signup(FimsUser user) {
		user.setAccount(user.getAccount().toUpperCase());
		boolean saved = userService.create(user);

		if("21".equals(user.getUserSeCd()))
			authorityService.addUsers("ROLE_RENT", user.getId());

		return new ModelAndView("jsonView")
			.addObject("saved",saved);
	}

	@RequestMapping(name="중복 확인", value="/duplicate.do")
	public ModelAndView isDuplicate(String account, String sggCd) {
		FimsUser user = userService.getUser(account.toUpperCase(), sggCd);
		return new ModelAndView("jsonView")
			.addObject("duplicate", user != null);
	}

	@RequestMapping(name="접속자 IP 확인", value="/ipInfo.do")
	public ModelAndView ipInfo(HttpServletRequest hreq) {
		String flag = hreq.getParameter("flag");
		String remoteAddr = AppCmmnUtil.getClientIpAddr(hreq);

		String net = "";
		String[] LOCAL = {"127.0.0.1", "0:0:0:0:0:0:0:1"};
		String[] PRIVATES = {
			"10.",
			"172.16.","172.17.","172.18.","172.19.","172.20.","172.21.","172.22.","172.23.",
			"172.24.","172.25.","172.26.","172.27.","172.28.","172.29.","172.30.","172.31.",
			"192.168."
		};
		String XIT_NET = "211.119.124.";
		List<String> EXTERNAL_ENT_NET = FimsConf.get().getExternalEntNet();
		List<String> SGG_NET = FimsConf.get().getSggNet();

		if(remoteAddr.equals(LOCAL[0]) || remoteAddr.equals(LOCAL[1])) {
			net = "intra";
		} else if(remoteAddr.startsWith(PRIVATES[0])
				|| remoteAddr.startsWith(PRIVATES[1])
				|| remoteAddr.startsWith(PRIVATES[2])
				|| remoteAddr.startsWith(PRIVATES[3])){
			net = "intra";
		} else if(remoteAddr.startsWith(XIT_NET)) {
			net = "intra";
		} else if(this.includeIp(remoteAddr,EXTERNAL_ENT_NET)){
			net = "intra";
		} else if(this.includeIp(remoteAddr,SGG_NET)) {
			net = "intra";
		}
		boolean flagUsable = !isEmpty(net);

		if(!isEmpty(flag)){
			if(flagUsable) {
				net = flag;
			}
		}
		if(isEmpty(net))
			net = "inter";

		return new ModelAndView("jsonView")
			.addObject("remoteAddr", remoteAddr)
			.addObject("net", net);
	}

	private boolean includeIp(String ipAddr, List<String> ipBand){
		boolean result = false;

		if(ipBand != null && ipBand.size() > 0){
			for(String item : ipBand) {
				if(item.endsWith(".")) {
					if(ipAddr.startsWith(item)) {
						result = true;
					}
				} else {
					if(ipAddr.equals(item)) {
						result = true;
					}
				}

			}
		}
		return result;
	}


	@RequestMapping(name="서버 이벤트 수신 등록", value="/subscribe.do")
	public SseEmitter subscribe(HttpServletRequest req) {
		return sseBean.start(req.getParameter("sseKey"));
	}
}