/*
 * This file is part of Nuts Framework.
 * Copyright(C) 2009-2012 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 * 
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.exts.struts2.actions;

import nuts.core.lang.Exceptions;
import nuts.core.lang.StringEscapes;
import nuts.core.lang.Strings;
import nuts.core.log.Log;
import nuts.core.log.Logs;
import nuts.core.servlet.HttpServletUtils;
import nuts.core.servlet.RequestLoggingFilter;
import nuts.core.servlet.UserAgent;
import nuts.core.util.Pager;
import nuts.core.util.Sorter;
import nuts.exts.struts2.interceptor.LayoutInterceptor;
import nuts.exts.struts2.util.StrutsContextUtils;
import nuts.exts.xwork2.StateProvider;
import nuts.exts.xwork2.util.ContextUtils;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;




/**
 */
public class ActionUtilities extends ActionHelper {
	private UserAgent userAgent;

	/**
	 * Constructor
	 * @param action action
	 */
	public ActionUtilities(CommonAction action) {
		super(action);
	}
	/**
	 * @return log
	 */
	public Log getLog() {
		return Logs.getLog(action.getClass());
	}
	
	/**
	 * @return true if action log is debug enabled
	 */
	public boolean isDebugEnabled() {
		return getLog().isDebugEnabled();
	}

	/**
	 * @return servlet exception stack trace
	 */
	public String getServletExceptionStackTrace() {
		HttpServletRequest req = StrutsContextUtils.getServletRequest();
		Throwable ex = (Throwable)req.getAttribute("javax.servlet.error.exception");
		if (ex != null) {
			return Exceptions.getStackTrace(ex);
		}
		else {
			return "";
		}
	}

	/**
	 * @return contextPath
	 */
	public String getContextPath() {
		return StrutsContextUtils.getServletRequest().getContextPath();
	}

	/**
	 * @return relativeURI
	 */
	public String getRelativeURI() {
		return HttpServletUtils.getRelativeURI(StrutsContextUtils.getServletRequest());
	}

	/**
	 * @return requestURI
	 */
	public String getRequestURI() {
		return HttpServletUtils.getRequestURI(StrutsContextUtils.getServletRequest());
	}
	
	/**
	 * @return requestURL
	 */
	public String getRequestURL() {
		return HttpServletUtils.getRequestURL(StrutsContextUtils.getServletRequest());
	}
	
	/**
	 * @return requestElapsedTime
	 */
	public String getRequestElapsedTime() {
		HttpServletRequest req = StrutsContextUtils.getServletRequest();
		Long start = (Long)req.getAttribute(RequestLoggingFilter.REQUEST_TIME);
		if (start != null) {
			long end = System.currentTimeMillis();
			long elapse = end - start;
			if (elapse < 1000) {
				return elapse + "ms";
			}
			else {
				return (elapse / 1000) + "s";
			}
		}
		return "";
	}
	
	/**
	 * @return csv file time string
	 */
	public String getCsvFileTime() {
		String format = getAction().getText("date-format-file", "_(yyyyMMdd-HHmmss)");
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(Calendar.getInstance().getTime());
	}

	/**
	 * @return server domain
	 */
	public String getServerDomain() {
		String sn = StrutsContextUtils.getServletRequest().getServerName();
		String[] ss = Strings.split(sn, ".");
		if (ss.length > 2) {
			return ss[ss.length - 2] + "." + ss[ss.length - 1];
		}
		else {
			return sn;
		}
	}

	/**
	 * @return system date
	 */
	public Date getSystemDate() {
		return Calendar.getInstance().getTime();
	}

	/**
	 * @return system year
	 */
	public String getSystemYear() {
		return String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
	}

	/**
	 * @return userAgent
	 */
	public UserAgent getUserAgent() {
		if (userAgent == null) {
			HttpServletRequest hsr = StrutsContextUtils.getServletRequest();
			userAgent = new UserAgent(hsr);
		}
		return userAgent;
	}

	/**
	 * @return browser string
	 */
	public String getBrowser() {
		String b = getUserAgent().toSimpleString();
		String l = getLayout();
		if (Strings.isNotEmpty(l)) {
			b += " layout-" + l;
		}
		return b;
	}

	/**
	 * @return layout
	 */
	public String getLayout() {
		return LayoutInterceptor.getLayout();
	}

	/**
	 * @return mobile layout
	 */
	public boolean isMobileLayout() {
		return LayoutInterceptor.MOBILE_LAYOUT.equals(getLayout());
	}
	
	/**
	 * load sorter parameters from stateProvider
	 * @param sorter sorter
	 * @throws Exception if an error occurs
	 */
	public void loadSorterParams(Sorter sorter) throws Exception {
		StateProvider sp = getAction().getStateProvider();
		
		if (Strings.isEmpty(sorter.getColumn())) {
			String sc = (String)sp.loadState("list.sc");
			if (Strings.isEmpty(sc)) {
				String tx = ContextUtils.getActionMethod() + NutsRC.SORTER_COLUMN_SUFFIX;
				sc = getAction().getText(tx, (String)null);
				if (sc == null && !NutsRC.LIST_SORTER_COLUMN.equals(tx)) {
					sc = getAction().getText(NutsRC.LIST_SORTER_COLUMN, (String)null);
				}
			}
			if (Strings.isNotEmpty(sc)) {
				sorter.setColumn(sc);
			}
		}
		if (Strings.isNotEmpty(sorter.getColumn())) {
			if (Strings.isEmpty(sorter.getDirection())) {
				String sd = (String)sp.loadState("list.sd");
				if (Strings.isEmpty(sd)) {
					String tx = ContextUtils.getActionMethod() + NutsRC.SORTER_DIRECTION_SUFFIX;
					sd = getAction().getText(tx, (String)null);
					if (sd == null && !NutsRC.LIST_SORTER_DIRECTION.equals(tx)) {
						sd = getAction().getText(NutsRC.LIST_SORTER_DIRECTION, (String)null);
					}
					if (sd == null) {
						sd = Sorter.ASC;
					}
				}
				sorter.setDirection(sd);
			}
		}
	}
	
	/**
	 * load pager limit parameters from stateProvider
	 * @param pager pager
	 * @throws Exception if an error occurs
	 */
	public void loadLimitParams(Pager pager) throws Exception {
		StateProvider sp = getAction().getStateProvider();
		if (pager.getLimit() == null || pager.getLimit() < 1) {
			try {
				pager.setLimit(Integer.parseInt((String)sp.loadState("list.pl")));
			}
			catch (Exception e) {
			}
		}
		if (pager.getLimit() == null || pager.getLimit() < 1) {
			String tx = ContextUtils.getActionMethod() + NutsRC.PAGER_LIMIT_SUFFIX;
			Integer l = getAction().getTextAsInt(tx);
			if (l == null && !NutsRC.LIST_PAGER_LIMIT.equals(tx)) {
				l = getAction().getTextAsInt(NutsRC.LIST_PAGER_LIMIT);
			}
			if (l == null) {
				l = NutsRC.DEFAULT_LIST_PAGER_LIMIT;
			}
			pager.setLimit(l);
		}
		limitPage(pager);
	}
	
	/**
	 * save sorter parameters to stateProvider
	 * @param sorter sorter
	 * @throws Exception if an error occurs
	 */
	public void saveSorterParams(Sorter sorter) throws Exception {
		StateProvider sp = getAction().getStateProvider();
		sp.saveState("list.sc", sorter.getColumn());
		sp.saveState("list.sd", sorter.getDirection());
	}
	
	/**
	 * save pager limit parameters to stateProvider
	 * @param pager pager
	 * @throws Exception if an error occurs
	 */
	public void saveLimitParams(Pager pager) throws Exception {
		StateProvider sp = getAction().getStateProvider();
		sp.saveState("list.pl", pager.getLimit());
	}
	
	/**
	 * if pager.limit > maxLimit then set pager.limit = maxLimit
	 * @param pager pager
	 */
	public void limitPage(Pager pager) {
		int maxLimit = getAction().getTextAsInt(NutsRC.PAGER_MAX_LIMIT, 100);
		if (pager.getLimit() == null 
				|| pager.getLimit() < 1 
				|| pager.getLimit() > maxLimit) {
			pager.setLimit(maxLimit);
		}
	}
	

	/**
	 * @see StringEscapes#escapeHtml(String)
	 */
	public String escapeHtml(String str) {
		return StringEscapes.escapeHtml(str);
	}
	
	/**
	 * @see StringEscapes#escapePhtml(String)
	 */
	public String escapePhtml(String str) {
		return StringEscapes.escapePhtml(str);
	}
	
	/**
	 * @see StringEscapes#escapeJava(String)
	 */
	public String escapeJava(String str) {
		return StringEscapes.escapeJava(str);
	}
	
	/**
	 * @see StringEscapes#escapeJavaScript(String)
	 */
	public String escapeJavaScript(String str) {
		return StringEscapes.escapeJavaScript(str);
	}
	
	/**
	 * @see StringEscapes#escapeXml(String)
	 */
	public String escapeXml(String str) {
		return StringEscapes.escapeXml(str);
	}
	
	/**
	 * @see StringEscapes#escapeCsv(String)
	 */
	public String escapeCsv(String str) {
		return StringEscapes.escapeCsv(str);
	}
	
	/**
	 * @see Strings#formatFileSize(Long)
	 */
	public String formatFileSize(long size) {
		return Strings.formatFileSize(size);
	}
	
	/**
	 * @see Strings#ellipsis(String, int)
	 */
	public String ellipsis(String str, int len) {
		return Strings.ellipsis(str, len);
	}
	
	/**
	 * @see Strings#ellipsiz(String, int)
	 */
	public String ellipsiz(String str, int len) {
		return Strings.ellipsiz(str, len);
	}
	
	/**
	 * @param name cookie name
	 * @return cookie value
	 */
	public String getCookie(String name) {
		Cookie c = HttpServletUtils.getCookie(StrutsContextUtils.getServletRequest(), name);
		return c != null ? c.getValue() : null;
	}

	/**
	 * @param str string
	 * @return array
	 */
	public String[] split(String str) {
		return Strings.split(str);
	}

	/**
	 * @return random id
	 */
	public String getRandomId() {
		return UUID.randomUUID().toString();
	}

}
