package xyz.wbsite.config;

import freemarker.template.SimpleScalar;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import xyz.wbsite.frame.auth.LocalData;
import xyz.wbsite.frame.base.Control;
import xyz.wbsite.frame.utils.UrlUtil;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.List;
import java.util.Locale;

import static xyz.wbsite.config.ActionConfig.CONTROL_PREFIX;
import static xyz.wbsite.config.ActionConfig.SCREEN_PREFIX;

@Configuration
public class FreeMarkerConfig {
    @Autowired
    private FreeMarkerViewResolver viewResolver;
    @Autowired
    private freemarker.template.Configuration configuration;
    @Value("${server.servlet.context-path}")
    private String context;

    private String suffix = ".ftl";

    @PostConstruct
    public void setSharedVariable() throws TemplateModelException {
        // 全局共享变量、函数
        configuration.setSharedVariable("context", context);
        configuration.setSharedVariable("screenHolder", new ScreenHolder());
        configuration.setSharedVariable("controlHolder", new ControlHolder());
        configuration.setSharedVariable("UrlUtil", new UrlUtil());
    }

    private class ScreenHolder implements TemplateMethodModelEx {

        @Override
        public Object exec(List list) throws TemplateModelException {
            try {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                LocaleResolver localeResolver = (LocaleResolver) request.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE);
                String servletPath = LocalData.getAction();
                servletPath = servletPath.replaceAll("^/", "");

                String[] split = servletPath.split("/");
                StringBuilder sb = new StringBuilder("");

                // 分割组装路径
                for (int i = 0; i < split.length; i++) {
                    sb.append(split[i]);
                    if (i != split.length - 1) {
                        sb.append(File.separator);
                    }
                }

                Locale locale = localeResolver.resolveLocale(request);
                String viewName = "screen" + File.separator + sb.toString();
                View view = viewResolver.resolveViewName(viewName, locale);
                //无法找到对应screen
                if (view == null) {
                    return "";
                } else {
                    return SCREEN_PREFIX + servletPath + suffix;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "";
        }
    }

    private class ControlHolder implements TemplateMethodModelEx {

        @Override
        public Object exec(List list) throws TemplateModelException {
            String control = "";
            if (list.size() != 1) {
                return "";
            }
            Object o = list.get(0);
            if (o instanceof SimpleScalar) {
                control = ((SimpleScalar) o).getAsString();
            }

            // 查找是否存在对应控制面板执行器
            Control controlExec = null;
            try {
                String beanClassName = (CONTROL_PREFIX + control).toLowerCase();
                controlExec = LocalData.getApplicationContext().getBean(beanClassName, Control.class);

                HttpServletRequest request = LocalData.getRequest();
                HttpServletResponse response = LocalData.getResponse();

                BindingAwareModelMap modelMap = new BindingAwareModelMap();
                controlExec.exec(modelMap, request, response);

                for (String key : modelMap.keySet()) {
                    request.setAttribute(key, modelMap.get(key));
                }
            } catch (BeansException e) {

            }

            control = control.replaceAll("/", File.separator);
            return CONTROL_PREFIX + control + suffix;
        }
    }
}
