package it.mice.voila.runtime.springmvc.taglibs;

import it.mice.voila.runtime.springmvc.bean.TabInfoBean;
import it.mice.voila.runtime.springmvc.util.SpringMvcUtil;
import it.mice.voila.runtime.web.menu.MenuFilterManager;

import java.util.Collection;
import java.util.Iterator;

import javax.servlet.jsp.JspException;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.tags.form.AbstractHtmlElementTag;
import org.springframework.web.servlet.tags.form.TagWriter;

public class TabsTag extends AbstractHtmlElementTag {
    private static final String RESOURCES_IMAGES = "/resources/images/";
	private static final String DOJO = "dojo";

	private String type = null;

	/**
	 */
	private static final long serialVersionUID = 1L;
	
	private Collection<TabInfoBean> tabs;
	private String tabId = "";
	private String currentTab = null;
	private String urlTemplate = null;
	private String onClick = null;
	private boolean wizard = false;

	/**
	 * @return the tabId
	 */
	public String getTabId() {
		return tabId;
	}

	/**
	 * @param tabId the tabId to set
	 */
	public void setTabId(String tabId) {
		this.tabId = tabId;
	}

	/**
	 * @return the type
	 */
	public String getType() {
		return type;
	}

	/**
	 * @param type the type to set
	 */
	public void setType(String type) {
		this.type = type;
	}

	public Collection<TabInfoBean> getTabs() {
		return tabs;
	}

	public void setTabs(Collection<TabInfoBean> tabs) {
		this.tabs = tabs;
	}

	public String getCurrentTab() {
		return currentTab;
	}

	public void setCurrentTab(String currentTab) {
		this.currentTab = currentTab;
	}

	/**
	 * @return the urlTemplate
	 */
	public String getUrlTemplate() {
		return urlTemplate;
	}

	/**
	 * @param urlTemplate the urlTemplate to set
	 */
	public void setUrlTemplate(String urlTemplate) {
		this.urlTemplate = urlTemplate;
	}

	/**
	 * @return the onClick
	 */
	public String getOnClick() {
		return onClick;
	}

	/**
	 * @param onClick the onClick to set
	 */
	public void setOnClick(String onClick) {
		this.onClick = onClick;
	}

	/**
	 * @return the wizard
	 */
	public boolean isWizard() {
		return wizard;
	}

	/**
	 * @param wizard the wizard to set
	 */
	public void setWizard(boolean wizard) {
		this.wizard = wizard;
	}

	@Override
	protected int writeTagContent(TagWriter tagWriter) throws JspException {
		if (TagUtils.isBootstrapTheme()) {
			writeBootstrapOutput(tagWriter);
		} else {
	        writeStandardOutput(tagWriter);
		}
        
        return EVAL_PAGE;
	}

	private void writeStandardOutput(TagWriter tagWriter) throws JspException {
		tagWriter.startTag("div");
        tagWriter.writeAttribute("id", "tabPaneDiv");
        tagWriter.startTag("ul");
        tagWriter.writeAttribute("id", "tabPane");
        tagWriter.writeAttribute("class", "tabs");
        
        Iterator<TabInfoBean> i = getTabs().iterator();
        int ctr = 0;
        boolean foundCurrentTab = false;
        while (i.hasNext()) {
			TabInfoBean tabInfoBean = i.next();
			if (!isAuthorized(tabInfoBean)) {
				if (getCurrentTab().equals(tabInfoBean.getTabName())) {
					setCurrentTab(i + "");
				}
				continue;
			}
			String currentTab = getCurrentTab();
			String className = "tab-active";
			String title = TagUtils.getMessage(getRequestContext(), tabInfoBean.getTabTitle());
			String stripedTitle = title != null ? it.mice.voila.runtime.util.StringUtils.stripHtml(title) : null;
			String content = TagUtils.getMessage(getRequestContext(), tabInfoBean.getTabContent());
			tagWriter.startTag("li");
			if (isActiveTab(ctr, tabInfoBean, currentTab) || (isWizard() && !foundCurrentTab)) {
		        if (isWizard()) {
		        	if (isActiveTab(ctr, tabInfoBean, currentTab)) {
		        		className = "tab-step-current";
		        	} else {
		        		className = "tab-step-done";
		        	}
		        } else {
		        	className = "tab-active";
		        }
		        className = addSepClassIfRequired(tabInfoBean, className);
		        tagWriter.writeAttribute("class", className);

				writeImage(tagWriter, tabInfoBean, title, true, true, className, ctr, stripedTitle);

		        tagWriter.startTag("span");
		        tagWriter.writeAttribute("id", "tab_" + ctr);
		        tagWriter.writeAttribute("class", className);
		        if (stripedTitle != null) {
			        tagWriter.writeAttribute("alt", stripedTitle);
			        tagWriter.writeAttribute("title", stripedTitle);
		        }
		        tagWriter.appendValue(content);
		        tagWriter.endTag();
				if (isActiveTab(ctr, tabInfoBean, currentTab)) {
					foundCurrentTab = true;
				}
			} else {
		        if (tabInfoBean.isDisabled() || isWizard()) {
		        	if (isWizard()) {
		        		className = "tab-step-todo";
		        	} else {
		        		className = "tab-disabled";
		        	}
			        className = addSepClassIfRequired(tabInfoBean, className);
			        tagWriter.writeAttribute("class", className);
		        } else if (tabInfoBean.isSep()) {
			        tagWriter.writeAttribute("class", "sep");
		        }
				if (!isWizard()) {
					tagWriter.startTag("a");
				}
		        tagWriter.writeAttribute("id", "tab_" + ctr);
		        if (stripedTitle != null) {
			        tagWriter.writeAttribute("title", stripedTitle);
		        }
		        if (tabInfoBean.isDisabled() || isWizard()) {
			        tagWriter.writeAttribute("class", className);
			        tagWriter.writeAttribute("onclick", "void(0);");
		        } else {
			        tagWriter.writeAttribute("href", prepareTabLink(tabInfoBean, ctr));
			        tagWriter.writeAttribute("onclick", (getOnClick() == null ? "return handleSwapTab(this)" : getOnClick()));
		        }
				writeImage(tagWriter, tabInfoBean, title, false, (isWizard() ? true : tabInfoBean.isDisabled()), className, ctr, stripedTitle);
				tagWriter.startTag("span");
		        tagWriter.appendValue(content);
		        tagWriter.endTag();
				if (!isWizard()) {
			        tagWriter.endTag();
				}
			}
	        tagWriter.endTag();
	        ctr++;
		}
        tagWriter.endTag();
        tagWriter.endTag();
	}


	private String addSepClassIfRequired(TabInfoBean tabInfoBean, String className) {
		String result = className;
		if (tabInfoBean.isSep()) {
			result += " sep";
		}
		return result;
	}

	private void writeBootstrapOutput(TagWriter tagWriter) throws JspException {
        tagWriter.startTag("ul");
        tagWriter.writeAttribute("id", "tabPane" + getTabId());
        tagWriter.writeAttribute("class", "nav nav-tabs " + getTabId());
        
        Iterator<TabInfoBean> i = getTabs().iterator();
        int ctr = 0;
        boolean foundCurrentTab = false;
        while (i.hasNext()) {
			TabInfoBean tabInfoBean = i.next();
			if (!isAuthorized(tabInfoBean)) {
				if (getCurrentTab().equals(tabInfoBean.getTabName())) {
					setCurrentTab(i + "");
				}
				continue;
			}
			String currentTab = getCurrentTab();
			String className = "active";
			String title = TagUtils.getMessage(getRequestContext(), tabInfoBean.getTabTitle());
			String stripedTitle = title != null ? it.mice.voila.runtime.util.StringUtils.stripHtml(title) : null;
			String content = TagUtils.getMessage(getRequestContext(), tabInfoBean.getTabContent());
			tagWriter.startTag("li");
			if (isActiveTab(ctr, tabInfoBean, currentTab) || (isWizard() && !foundCurrentTab)) {
		        if (isWizard()) {
		        	if (isActiveTab(ctr, tabInfoBean, currentTab)) {
		        		className = "tab-step-current";
		        	} else {
		        		className = "tab-step-done";
		        	}
		        } else {
		        	className = "active";
		        }
		        tagWriter.writeAttribute("role", "presentation");
		        className = addSepClassIfRequired(tabInfoBean, className);
		        tagWriter.writeAttribute("class", className);

				//writeImage(tagWriter, tabInfoBean, title, true, true, className, ctr, stripedTitle);

		        tagWriter.startTag("a");
		        tagWriter.writeAttribute("id", "tab_" + getTabId() + ctr);
		        tagWriter.writeAttribute("href", "#");
		        if (stripedTitle != null) {
			        tagWriter.writeAttribute("alt", stripedTitle);
			        tagWriter.writeAttribute("title", stripedTitle);
		        }
		        tagWriter.appendValue(content);
		        tagWriter.endTag();
				if (isActiveTab(ctr, tabInfoBean, currentTab)) {
					foundCurrentTab = true;
				}
			} else {
		        if (tabInfoBean.isDisabled() || isWizard()) {
		        	if (isWizard()) {
		        		className = "tab-step-todo";
		        	} else {
		        		className = "tab-disabled";
		        	}
			        className = addSepClassIfRequired(tabInfoBean, className);
			        tagWriter.writeAttribute("class", className);
		        } else if (tabInfoBean.isSep()) {
			        tagWriter.writeAttribute("class", "sep");
		        }
				if (!isWizard()) {
					tagWriter.startTag("a");
				}
		        tagWriter.writeAttribute("id", "tab_" + getTabId() + ctr);
		        if (stripedTitle != null) {
			        tagWriter.writeAttribute("title", stripedTitle);
		        }
		        if (tabInfoBean.isDisabled() || isWizard()) {
			        tagWriter.writeAttribute("class", className);
			        tagWriter.writeAttribute("onclick", "void(0);");
		        } else {
			        tagWriter.writeAttribute("href", prepareTabLink(tabInfoBean, ctr));
			        tagWriter.writeAttribute("onclick", (getOnClick() == null ? "return handleSwapTab(this)" : getOnClick()));
		        }
//				writeImage(tagWriter, tabInfoBean, title, false, (isWizard() ? true : tabInfoBean.isDisabled()), className, ctr, stripedTitle);
		        tagWriter.appendValue(content);
				if (!isWizard()) {
			        tagWriter.endTag();
				}
			}
	        tagWriter.endTag();
	        ctr++;
		}
        tagWriter.endTag();
	}

	/**
	 * @param ctr
	 * @param tabInfoBean
	 * @param currentTab
	 * @return
	 */
	private boolean isActiveTab(int ctr, TabInfoBean tabInfoBean,
			String currentTab) {
		if (NumberUtils.isDigits(currentTab)) {
			return currentTab.equals(ctr + "");
		}
		return currentTab.equals(tabInfoBean.getTabName());
	}

	private boolean isAuthorized(TabInfoBean tabInfoBean) {
		String contextPath = getRequestContext().getContextPath();
		String currentUri = getRequestContext().getRequestUri();

		String relativeUri = StringUtils.difference(contextPath, currentUri);
		String[] urlParts = StringUtils.split(relativeUri, '/');
		String baseUrl = "/" + urlParts[0] + "/" + urlParts[1] + "/component/list" + tabInfoBean.getTabName() + "For";
		String formName = StringUtils.capitalize(urlParts[1]);
		baseUrl += formName;
		
        MenuFilterManager menuFilterManager =
        	(MenuFilterManager)WebApplicationContextUtils
        	.getRequiredWebApplicationContext(
        			SpringMvcUtil.getServletContext())
        			.getBean("menuFilterManager");
        
	    return !menuFilterManager.disableMenuItem(baseUrl);
	}

	private void writeImage(TagWriter tagWriter, TabInfoBean tabInfoBean, String title, boolean isActive, boolean isLinkDisabled, String className, int ctr, String stripedTitle) throws JspException {
		String imagePath = getRequestContext().getContextPath() + RESOURCES_IMAGES + (getIconImageName(isActive, className, tabInfoBean)) + ".gif";
		String userImage = getUserImage(tabInfoBean, isActive, className);
		if (userImage != null) {
			if (userImage.startsWith("/")) {
				imagePath = getRequestContext().getContextPath() + userImage;
			} else {
				imagePath = getRequestContext().getContextPath() + RESOURCES_IMAGES + userImage;
			}
		}
		
		if(isLinkDisabled){
			tagWriter.startTag("img");
			tagWriter.writeAttribute("src", imagePath);
			tagWriter.writeAttribute("class", "noBorder");
	        if (stripedTitle != null) {
				tagWriter.writeAttribute("alt", stripedTitle);
				tagWriter.writeAttribute("title", stripedTitle);
	        }
	        tagWriter.writeAttribute("id", "tab_image" + getTabId() + ctr);
			tagWriter.endTag();
		} else {
			tagWriter.startTag("input");
			tagWriter.writeAttribute("type", "image");
			tagWriter.writeAttribute("src", imagePath);
			tagWriter.writeAttribute("class", "noBorder");
	        if (stripedTitle != null) {
				tagWriter.writeAttribute("alt", stripedTitle);
				tagWriter.writeAttribute("title", stripedTitle);
	        }
	        tagWriter.writeAttribute("id", "tab_image" + getTabId() + ctr);
			tagWriter.endTag();
		}
		
        if (title != null) {
    		String strippedTitle = it.mice.voila.runtime.util.StringUtils.stripCrLf(title);
    		if (DOJO.equals(getType())) {
    			tagWriter.startTag("script");
    			tagWriter.writeAttribute("type", "text/javascript");
    			tagWriter.appendValue("dojo.addOnLoad(function() {");
    			tagWriter.appendValue("new dijit.Tooltip({connectId: [\"" + "tab_image" + ctr + "\"], label: \"" + strippedTitle + "\"});");
    			tagWriter.appendValue("document.getElementById(\"" + "tab_image" + ctr + "\").title = \"\";");
    			tagWriter.appendValue("new dijit.Tooltip({connectId: [\"" + "tab_" + ctr + "\"], label: \"" + strippedTitle + "\"});");
    			tagWriter.appendValue("document.getElementById(\"" + "tab_" + ctr + "\").title = \"\";");
    			tagWriter.appendValue("});");
    			tagWriter.endTag();
    		}
        }
	}

	private String getIconImageName(boolean isActive, String className, TabInfoBean tabInfoBean) {
		if ("tab-step-current".equals(className)) {
			return "step-current";
		}
		if ("tab-step-done".equals(className)) {
			return "step-done";
		}
		if ("tab-step-todo".equals(className)) {
			return "step-todo";
		}

		return isActive ? "on" : "off";
	}
	
	private String getUserImage(TabInfoBean tabInfoBean, boolean isActive, String className) {
		if ("tab-step-current".equals(className)) {
			return tabInfoBean.getImageCurrent();
		}
		if ("tab-step-done".equals(className)) {
			return tabInfoBean.getImageDone();
		}
		if ("tab-step-todo".equals(className)) {
			return tabInfoBean.getImageTodo();
		}

		return isActive ? tabInfoBean.getImageOn() : tabInfoBean.getImageOff();
	}
	
	private String prepareTabLink(TabInfoBean tabInfoBean, int ctr) {
		String contextPath = getRequestContext().getContextPath();
		String baseUri = getRequestContext().getRequestUri();
		if (baseUri.lastIndexOf("?") > -1) {
			baseUri += "&amp;";
		} else {
			baseUri += "?";
		}
		String urlTemplate = (getUrlTemplate() != null ? getUrlTemplate() : "{currentUrl}");
		String result = formatUrl(urlTemplate, baseUri, contextPath, tabInfoBean);
		result += "?tabIndex"  + getTabId() + "=" + ctr;
		result += "&jumpTo=tab_" + getTabId() + ctr;

		if (tabInfoBean.getOtherParams() != null) {
			result += "&" + tabInfoBean.getOtherParams();
		}
        //TagUtils.getSecuritySessionBean().addFormField("currentTab", tabInfoBean.getTabName(), "hidden");
        TagUtils.getSecuritySessionBean().addFormField("jumpTo", "tab_" + getTabId() + ctr, "hidden");

		return result;
	}

	private String formatUrl(String urlTemplate, String baseUri, String contextPath, TabInfoBean tabInfoBean) {
		String result = urlTemplate;
		result = StringUtils.replace(result, "{currentUrl}", baseUri);
		result = StringUtils.replace(result, "{contextPath}", contextPath);
		result = StringUtils.replace(result, "{tabName}", tabInfoBean.getTabName());
		if (result.endsWith("?")) {
			result = result.substring(0, result.length() - 1);
		}
		return result;
	}
	
	/**
	 * Clears the stored {@link TagWriter}.
	 */
	@Override
	public void doFinally() {
		super.doFinally();

		setTabId("");
		setType(null);
		setTabs(null);
		setCurrentTab(null);
		setUrlTemplate(null);
		setOnClick(null);
	}

}
