package eu.dnetlib.functionality.modular.ui;

import java.net.URLEncoder;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import eu.dnetlib.functionality.modular.ui.users.AuthorizationManager;
import eu.dnetlib.functionality.modular.ui.users.User;
import eu.dnetlib.functionality.modular.ui.utils.ShutdownUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.ModelMap;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.view.RedirectView;

public abstract class ModuleEntryPoint extends MenuEntry implements Controller, BeanNameAware {

	@Autowired
	protected EntryPointsAggregator aggregator;
	@Resource(name = "modularUiAuthorizationManager")
	protected AuthorizationManager authorizationManager;
	private String beanName;
	private boolean validMenuEntry = true;
	private String group;
	private int groupOrder = 50;
	@Value("${dnet.modular.ui.authentication.url}")
	private String authenticationUrl;
	@Value("${dnet.modular.ui.logout.url}")
	private String logoutUrl;
	@Value("${dnet.modular.ui.ribbon.environment}")
	private String environment;
	@Value("${dnet.modular.ui.ribbon.accent}")
	private String ribbonAccent;
	@Autowired
	private ShutdownUtils shutdownUtils;

	@Override
	public ModelAndView handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception {

		final User user = this.authorizationManager.obtainUserDetails(request);
		if (user != null) {
			final ModelAndView mv = new ModelAndView();
			final ModelMap map = mv.getModelMap();
			map.addAttribute("ui_menu", getMenu());
			map.addAttribute("ui_title", getTitle());
			map.addAttribute("ui_description", getDescription());
			map.addAttribute("ui_group", getGroup());
			map.addAttribute("ui_modules", this.aggregator.getMenus(user));
			map.addAttribute("environment", this.environment);
			map.addAttribute("ribbonAccent", this.ribbonAccent);

			switch (this.shutdownUtils.currentStatus()) {
			case STOPPING:
				map.addAttribute("ui_navbar_class", "navbar-system-stopping");
				map.addAttribute("ui_message", "stopping system");
				break;
			case STOPPED:
				map.addAttribute("ui_navbar_class", "navbar-system-stopped");
				map.addAttribute("ui_message", "system stopped");
				break;
			default:
				map.addAttribute("ui_navbar_class", "navbar-inverse");
				break;
			}

			String baseUrl = "";
			for (int i = 1; i < StringUtils.countMatches(this.beanName, "/"); i++) {
				baseUrl += "/..";
			}
			if (baseUrl.length() > 0) {
				baseUrl = baseUrl.substring(1);
			}

			map.addAttribute("ui_baseUrl", baseUrl);

			if ((this.logoutUrl != null) && !this.logoutUrl.isEmpty()) {
				map.addAttribute("ui_logoutUrl", this.logoutUrl);
			}

			map.addAttribute("ui_user", user);

			initialize(map, request, response);
			return mv;
		} else {
			final StringBuffer url = request.getRequestURL();
			final String queryString = request.getQueryString();
			if (queryString != null) {
				url.append('?');
				url.append(queryString);
			}
			return new ModelAndView(new RedirectView(this.authenticationUrl + "?url=" + URLEncoder.encode(url.toString(), "UTF-8")));
		}
	}

	abstract protected void initialize(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws Exception;

	public String getBeanName() {
		return this.beanName;
	}

	@Override
	public void setBeanName(final String beanName) {
		this.beanName = beanName;
	}

	public String getGroup() {
		return this.group;
	}

	@Required
	public void setGroup(final String group) {
		this.group = group;
	}

	@Override
	public String getRelativeUrl() {
		return this.beanName;
	}

	public boolean isValidMenuEntry() {
		return this.validMenuEntry;
	}

	public void setValidMenuEntry(final boolean validMenuEntry) {
		this.validMenuEntry = validMenuEntry;
	}

	public int getGroupOrder() {
		return this.groupOrder;
	}

	public void setGroupOrder(final int groupOrder) {
		this.groupOrder = groupOrder;
	}

}
