package com.eactive.httpmockserver.api.controller;

import com.eactive.httpmockserver.api.entity.MockRoute;
import com.eactive.httpmockserver.api.service.MockRouteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

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

@Component
public class MockApiHandlerMapping {

    private static final Logger logger = LoggerFactory.getLogger(MockApiHandlerMapping.class);

    @Autowired
    private MockRouteService mockRouteService;

    @Autowired
    private MockApiController mockApiController;

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @PostConstruct
    public void initialize() {
        mockRouteService.initAllRoutes();
        for (MockRoute mockRoute : mockRouteService.getAllRoutes()) {
            registerMapping(mockRoute);
        }
    }

    public void registerMapping(MockRoute mockRoute) {
        RequestMappingInfo mappingInfo = RequestMappingInfo
                .paths(mockRoute.getPathPattern())
                .methods(RequestMethod.valueOf(mockRoute.getMethod()))
                .build();

        try {
            requestMappingHandlerMapping.registerMapping(mappingInfo, mockApiController, MockApiController.class.getDeclaredMethod("handleRequest", HttpServletRequest.class));
            logger.info("Registered mapping for {} {}", mockRoute.getMethod(), mockRoute.getPathPattern());
        } catch (NoSuchMethodException e) {
            logger.error("Error registering mapping", e);
        }
    }

    public void unregisterMapping(MockRoute mockRoute) {
        RequestMappingInfo mappingInfo = RequestMappingInfo
                .paths(mockRoute.getPathPattern())
                .methods(RequestMethod.valueOf(mockRoute.getMethod()))
                .build();

        requestMappingHandlerMapping.unregisterMapping(mappingInfo);
        logger.info("Unregistered mapping for {} {}", mockRoute.getMethod(), mockRoute.getPathPattern());
    }
}
