package ru.yandex.webmaster3.viewer.market_compat;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * @author avhaliullin
 */
public class MarketCompatibilityActionsHandler extends AbstractHandler implements ApplicationContextAware {
    private static final Logger log = LoggerFactory.getLogger(MarketCompatibilityActionsHandler.class);

    private static final String TARGET_PREFIX = "/market-compat/";
    private static final XmlMapper OM = new XmlMapper();

    static {
        OM.enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION);
        OM.disable(ToXmlGenerator.Feature.WRITE_XML_1_1);
        OM.setConfig(OM.getSerializationConfig().withRootName("data"));
    }

    private ApplicationContext applicationContext;
    private Map<String, AbstractCompatAction> actionsMap;

    public void init() {
        actionsMap = applicationContext.getBeansOfType(AbstractCompatAction.class);
    }

    @Override
    public void handle(String target, Request baseRequest, HttpServletRequest request,
                       HttpServletResponse response) throws IOException, ServletException {
        try {
            if (target.startsWith(TARGET_PREFIX)) {
                target = target.substring(TARGET_PREFIX.length());
                AbstractCompatAction action = actionsMap.get("compat-" + target + "Action");
                if (action != null) {
                    try {
                        Object result = action.process(baseRequest);
                        render(response, result);
                    } catch (MarketCompatErrorException e) {
                        render(response, e.response);
                    }
                    baseRequest.setHandled(true);
                }
            }
        } catch (Exception e) {
            log.error("Failed to process request for " + target, e);
        }
    }

    private void render(HttpServletResponse response, Object respObj) {
        response.setHeader("Content-Type", "application/xml; charset=UTF-8");
        try {
            OM.writeValue(response.getWriter(), respObj);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
