package com.its.vms.webapp.controller;

import com.its.vms.config.ApplicationConfig;
import com.its.vms.domain.NET;
import com.its.vms.dto.TbVmsCtlrDto;
import com.its.vms.service.AppRepositoryService;
import com.its.vms.webapp.service.FileService;
import com.its.vms.xnettcp.vms.handler.VmsServerIdleStateHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@RequiredArgsConstructor
@Controller
public class WebAppController {

    private final ResourceLoader resourceLoader;
    private final ApplicationConfig applicationConfig;
    private final AppRepositoryService repoService;
    private final FileService fileService;

    @RequestMapping(value = {"/controller"})
    public String controller(Model model, HttpServletRequest request) {
        String result = "controller";
        SortedMap<Long, TbVmsCtlrDto> ctlrMap = new TreeMap<>();        //for (Map.Entry<Long, TbVmsCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
        for (Map.Entry<Long, TbVmsCtlrDto> e : this.repoService.getCtlrMap().entrySet()) {
            TbVmsCtlrDto obj = e.getValue();
            if (obj.getNetState() == NET.CLOSED) {
                if (obj.getChannel() != null) {
                    obj.setNetState(NET.LOGINED);
                }
            }
            ctlrMap.put(obj.getVmsCtlrNmbr(), obj);
        }
        model.addAttribute("ServerConfig", this.applicationConfig);
        model.addAttribute("list", ctlrMap);
        model.addAttribute("ServerTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        return result;
    }

    @RequestMapping("/getControllerInfo")
    @ResponseBody
    public ConcurrentHashMap<Long, TbVmsCtlrDto> getControllerInfo() {
        ConcurrentHashMap<Long, TbVmsCtlrDto> ctlrMap = new ConcurrentHashMap<>();
        for (Map.Entry<Long, TbVmsCtlrDto> e : this.repoService.getCtlrMap().entrySet()) {
            TbVmsCtlrDto obj = e.getValue();
            ctlrMap.put(obj.getVmsCtlrNmbr(), obj);
        }
        return ctlrMap;
    }

    @RequestMapping(value = ("/disconnectController"))
    @ResponseBody
    public String disconnectController(@RequestParam("id") Long id) {
        String result = "제어기와의 통신 연결을 종료 하였습니다.";
        TbVmsCtlrDto ctlr = this.repoService.getCtrlMap(id);
        if (ctlr != null && ctlr.getNetState() > NET.CLOSED && ctlr.getChannel() != null) {
            VmsServerIdleStateHandler.disconnectChannel(ctlr, ctlr.getChannel());
        }
        else {
            result = "제어기는 현재 연결되어 있지 않습니다.";
        }
        return result;
    }

    @RequestMapping(value = ("/allDisconnectController"))
    @ResponseBody
    public String allDisconnectController() {
        String result = "통신 연결 중인 제어기와의 통신 연결을 종료 하였습니다.";
        for (Map.Entry<Long, TbVmsCtlrDto> e : this.repoService.getCtlrMap().entrySet()) {
            TbVmsCtlrDto ctlr = e.getValue();
            if (ctlr.getChannel() != null) {
                VmsServerIdleStateHandler.disconnectChannel(ctlr, ctlr.getChannel());
            }
        }
        return result;
    }

    @RequestMapping(value = ("/resetConnCount"))
    @ResponseBody
    public String resetConnCount(@RequestParam("id") Long id) {
        String result = "통신 접속횟수를 초기화 하였습니다.";
        TbVmsCtlrDto ctlr = this.repoService.getCtrlMap(id);
        if (ctlr != null) {
            ctlr.resetConnectCount();
        }
        return result;
    }

    @RequestMapping(value = ("/allResetConnCount"))
    @ResponseBody
    public String allResetConnCount() {
        String result = "모든 제어기의 통신 접속횟수를 초기화 하였습니다.";
        for (Map.Entry<Long, TbVmsCtlrDto> e : this.repoService.getCtlrMap().entrySet()) {
            TbVmsCtlrDto ctlr = e.getValue();
            ctlr.resetConnectCount();
        }
        return result;
    }

    @RequestMapping(value = ("/resetController"))
    @ResponseBody
    public String resetController(@RequestParam("id") Long id) {
        String result = "제어기를 리셋 하였습니다.";
        TbVmsCtlrDto ctlr = this.repoService.getCtrlMap(id);
        if (ctlr != null && ctlr.getNetState() > NET.CLOSED && ctlr.getChannel() != null) {
            VmsServerIdleStateHandler.disconnectChannel(ctlr, ctlr.getChannel());
        }
        else {
            result = "제어기는 현재 연결되어 있지 않습니다.";
        }
        return result;
    }

    @RequestMapping(value = ("/allResetController"))
    @ResponseBody
    public String allResetController(@RequestParam("id") String id) {
        String result = "통신 연결 중인 제어기를 리셋 하였습니다.";
        for (Map.Entry<Long, TbVmsCtlrDto> e : this.repoService.getCtlrMap().entrySet()) {
            TbVmsCtlrDto ctlr = e.getValue();
            if (ctlr != null && ctlr.getNetState() > NET.CLOSED && ctlr.getChannel() != null) {
                VmsServerIdleStateHandler.disconnectChannel(ctlr, ctlr.getChannel());
            }
        }
        return result;
    }

}
