package com.udapsoft.waf.system;

import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Properties;

import kr.co.hsnc.common.logger.Logger;
import kr.co.hsnc.common.sql.WAFConnection;
import kr.co.hsnc.common.sql.WAFSQLException;
import kr.co.hsnc.common.util.Translator;
import kr.co.hsnc.common.util.ValueObject;
import kr.co.hsnc.j2ee.waf.controller.web.util.WebKeys;

import com.udapsoft.waf.common.web.paging.PageAnchorInfo;

/**
 * Biz-Class의 디폴트의 구현을 제공합니다. Biz-Class는 본 클래스를 상속받아 Biz-Logic을 구현합니다.<br>
 * Biz-Class는 생성될때 HandlerStorage를 받아서 생성됩니다.<br>
 * IPSBiz는 Handler에 대해 일관한 인터페이스를 제공합니다.<br>
 * IPSBiz는 HandlerStorage에 대해 쉬운 접근을 제공합니다.(WAFConnection, PageAnchorInfo,
 * params...)<br>
 * 그외에 HandlerStorage의 리소스 및 Method는 HandlerStorage를 직접 접근 하여 사용한다.<br>
 * 
 * @author DaeJin Lee
 */
public abstract class Biz {

	/**
	 * Handler Storage
	 */
	protected HandlerStorage storage = null;

	/**
	 * JDBC DataBase Connection
	 */
	protected WAFConnection conn = null;

	/**
	 * Paging 처리를 위한 Helper Class
	 */
	protected PageAnchorInfo anchor = null;

	/**
	 * 전송받은 Parameter를 적재한 ValueObject
	 */
	protected ValueObject params = null;

	/**
	 * Biz-Class는 다음 생성자를 구현합니다.
	 * 
	 * @param storage
	 */
	protected Biz(HandlerStorage storage) {
		this.storage = storage;
		this.conn = storage.getWAFConnection();
		this.anchor = storage.getPageAnchorInfo();
		this.params = storage.getParams();
	}

	/**
	 * Paging 처리를 위한 Helper Class 생성합니다.
	 */
	protected void createPageAnchorInfo() {

		storage.createPageAnchorInfo();
		this.anchor = storage.getPageAnchorInfo();
	}

	/**
	 * 전송된 Parameter를 리턴한다.
	 * 
	 * @param key
	 * @return
	 */
	protected String get(String key) {

		return this.params.get(key);
	}

	/**
	 * 전송된 Parameter를 리턴한다.(값을 없는 경우에는 넘겨받은 기본값을 리턴한다.)
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	protected String get(String key, String defaultValue) {

		return this.params.get(key, defaultValue);
	}

	/**
	 * Array로 전송된 Parameter를 리턴한다.
	 * 
	 * @param key
	 * @return
	 */
	protected String[] gets(String key) {

		if (this.params.getObject(key) instanceof String[])
			return (String[]) (this.params.getObject(key));
		else {
			if ("".equals(this.params.get(key))) {
				String[] temp = { "" };
				return temp;
			} else {
				String[] temp = { this.params.get(key) };
				return temp;
			}
		}
	}

	/**
	 * Exception에 대한 통일된 로그 처리를 한다.
	 * 
	 * @param Exception
	 */
	protected void doException(Throwable e) {
		e.printStackTrace();
		StackTraceElement element = e.getStackTrace()[1];
		Logger.err.println(element.getClassName() + " --> " + element.getMethodName() + " : " + e.getMessage());
		Logger.err.println("URI : " + storage.getCurrentURI());
		Logger.err.println("EVENT : " + storage.getEvent());
		Logger.err.println("File  Name  : " + element.getFileName());
		Logger.err.println("Line Number : " + element.getLineNumber());
		Logger.err.printStackTrace((Exception) e);
	}

	/**
	 * Exception에 대한 통일된 로그 처리를 한다.
	 * 
	 * @param Exception
	 * @param search
	 */
	protected void doException(WAFSQLException se) {
		doException((Throwable) se);
		Logger.err.println("SQL : \n" + se.getStatement());
		Logger.err.println("PARAM : \n" + se.getParameter());
	}

	
	/**
	 * MultiPart 첨부파일을 리턴
	 * 
	 * @param key
	 * @return
	 */
	public java.io.File getFile(String key) {
		return this.storage.getFile(key);
	}

	/**
	 * File Key Set를 리턴
	 * 
	 * @return
	 */
	public Enumeration<?> getFileKeys() {
		return this.storage.getFileKeys();
	}

	/**
	 * MultiPart 첨부파일 원본 파일이름을 리턴
	 * 
	 * @param key
	 * @return
	 */
	public String getOriginalFileName(String key) {
		return this.storage.getOriginalFileName(key);
	}

	/**
	 * MultiPart 첨부파일에 ContentType을 리턴
	 * 
	 * @param key
	 * @return
	 */
	public String getContentType(String key) {
		return this.storage.getContentType(key);
	}

	/**
	 * 사용자 정보를 리턴
	 * 
	 * @return
	 */
	public ValueObject getUser() {
		return this.storage.getUser();
	}

	/**
	 * 사용자 정보를 세팅
	 * 
	 * @param user
	 *            사용자 정보
	 */
	public void setUser(ValueObject user) {
		this.storage.setUser(user);
	}

	/**
	 * 리소스 파일을 로드하여 ValueObject로 리턴 Default resourceName : "_message.resource"
	 * 
	 * @return
	 */
	public ValueObject getMessageResorce() {
		return getMessageResorce("_message.resource");
	}

	/**
	 * 리소스 파일을 로드하여 ValueObject로 리턴
	 * 
	 * @param resourceName
	 *            : 읽을 파일 이름(Biz Class와 같은 위치에 있는 파일 이름)
	 * @return
	 */
	public ValueObject getMessageResorce(String resourceName) {
		ValueObject messages = new ValueObject(true);
		Locale locale = (Locale) (this.storage.getRequest().getSession().getAttribute(WebKeys.LOCALE));
		String localeStr = locale.toString() + ".";
		
		try {
			InputStream stream = this.getClass().getResourceAsStream(resourceName);
			Properties prop = new Properties();
			prop.load(stream);
			stream.close();
			for (Enumeration<?> e = prop.keys(); e.hasMoreElements();) {
				String key = (String) e.nextElement();
				String value = prop.getProperty(key);
				String t_key = key;
				int index = key.indexOf(localeStr);
				if (index > -1) {
					t_key = key.substring(index + localeStr.length());
				}
				messages.set(t_key, Translator.toKSC(value));
			}
			
		} catch (Exception e) {
			Logger.err.printStackTrace(e);
		}
		return messages;
	}

	private static int key_seq = 0;
	private PrintWriter writer = null;

	protected void initInstanceLog(Class<?> cls) {
		initInstanceLog(cls, "" + key_seq);
	}

	protected void initInstanceLog(Class<?> cls, String key) {
		try {
			String path = "./logs";
			// path = WAFConfig.get("biz.instance.log.path");
			java.io.FileWriter fw = new java.io.FileWriter(path + key + ".log",
					true);
			writer = new PrintWriter(new java.io.BufferedWriter(fw), true);
		} catch (Exception e) {

		}
	}

	protected void log(String str) {
		if (writer != null) {
			writer.print(str);
		}
	}

	/**
	 * Biz-Logic을 구현하는 일관한 메서드 제공<BR>
	 * 다음 Method에 Biz-Logic을 구현한다.
	 * @throws Exception
	 */
	public abstract void doBiz() throws Exception;
}