/**
 * ÀÌ ¼Ò½º´Â Spring ÇÁ·¹ÀÓ¿öÅ© ¿öÅ©ºÏ¿¡¼­ »ç¿ëÇÑ ¿¹Á¦ ¼Ò½ºÀÔ´Ï´Ù. 
 * ÀÌ ¼Ò½º´Â ¸ðµç °³¹ßÀÚµéÀÌ ÀÚÀ¯·Ó°Ô ¼öÁ¤ ¹× ¹èÆ÷ÇÒ ¼ö ÀÖ½À´Ï´Ù. 
 * ´Ü, ÀÌ ¼Ò½º¸¦ ±â¹ÝÀ¸·Î »õ·Î¿î ¾ÖÇÃ¸®ÄÉÀÌ¼ÇÀ» °³¹ßÇÒ °æ¿ì ÃâÃ³¸¦ ¸í½ÃÇØ ÁÖ½Ã¸é µË´Ï´Ù. 
 */
package net.javajigi.board.service;

import java.util.List;

import net.javajigi.board.dao.BoardDAO;
import net.javajigi.board.dao.BoardFileDAO;
import net.javajigi.board.model.Board;
import net.javajigi.board.model.BoardFile;
import net.javajigi.common.util.DateTimeUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class PragrammaticBoardService implements BoardService {
	protected final Log logger = LogFactory.getLog(getClass());;

	private PlatformTransactionManager transactionManager;

	private BoardDAO boardDAO = null;

	private BoardFileDAO boardFileDAO = null;

	public void setTransactionManager(
			PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}	
	
	public void setBoardDAO(BoardDAO newBoardDAO) {
		this.boardDAO = newBoardDAO;
	}

	public void setBoardFileDAO(BoardFileDAO newBoardFileDAO) {
		this.boardFileDAO = newBoardFileDAO;
	}

	private TransactionDefinition getDefinition(int isolationLevel,
			boolean isReadOnly) {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition(
				TransactionDefinition.PROPAGATION_REQUIRED);
		def.setTimeout(5000);
		def.setReadOnly(isReadOnly);
		def.setIsolationLevel(isolationLevel);

		return def;
	}

	public Board addBoard(Board board) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, false));

		Board result = null;
		try {
			board.setCreateDate(DateTimeUtil
					.getDateTimeByPattern("yyyyMMddHHmmss"));
			result = boardDAO.insert(board);

			if (logger.isDebugEnabled()) {
				logger.debug("added new board!!. New Board ID : "
						+ result.getBoardNo());
			}

			boardFileDAO.insert(result.getBoardNo(), board.getBoardFiles());

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}

	public Board updateBoard(Board board) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, false));
		Board result = null;
		try {
			result = boardDAO.update(board);
			if (logger.isDebugEnabled()) {
				logger.debug("updated board!!. Update Board ID : "
						+ result.getBoardNo());
			}

			boardFileDAO.insert(result.getBoardNo(), board.getBoardFiles());

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}

	public int removeBoard(int boardNo) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, false));
		int result = 0;
		try {
			boardFileDAO.deleteByBoardNo(boardNo);
			result = boardDAO.delete(boardNo);

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}

	public Board findBoard(int boardNo) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, true));
		Board result = null;
		try {
			result = boardDAO.findBoard(boardNo);
			result.setBoardFiles(boardFileDAO.findBoardFileList(boardNo));

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}

	public Board findBoardWithView(int boardNo) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, false));
		Board result = null;
		try {
			boardDAO.updateHitCount(boardNo);
			result = findBoard(boardNo);

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.javajigi.board.service.BoardService#findBoardFile(int)
	 */
	public BoardFile findBoardFile(int boardFileNo) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, true));
		BoardFile result = null;

		try {
			result = boardFileDAO.findBoardFile(boardFileNo);

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.javajigi.board.service.BoardService#findBoardList(int, int)
	 */
	public List findBoardList(int currentPage, int countPerPage) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, true));

		List resultList = null;
		try {
			resultList = boardDAO.findBoardList(currentPage, countPerPage);

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return resultList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.javajigi.board.service.BoardService#updateHitCount(int)
	 */
	public int updateHitCount(int boardNo) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, false));

		int result = 0;
		try {
			result = boardDAO.updateHitCount(boardNo);

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.javajigi.board.service.BoardService#removeBoardFile(int)
	 */
	public int removeBoardFile(int fileNo) {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, true));

		int result = 0;
		try {
			result = boardFileDAO.deleteByBoardFileNo(fileNo);

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.javajigi.board.service.BoardService#getTotalNo()
	 */
	public int getBoardTotalCount() {
		TransactionStatus status = transactionManager
				.getTransaction(getDefinition(
						TransactionDefinition.ISOLATION_READ_COMMITTED, true));

		int result = 0;
		try {
			result = boardDAO.getTotalNo();

			transactionManager.commit(status);
		} catch (Throwable t) {
			transactionManager.rollback(status);

			if (t instanceof RuntimeException) {
				throw (RuntimeException) t;
			}
		}

		return result;
	}
}
