package jp.co.argo21.nautica.workflow.sample.control;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import jp.co.argo21.nautica.workflow.sample.model.AppTransaction;
import jp.co.argo21.nautica.workflow.sample.model.Application;
import jp.co.argo21.nautica.workflow.sample.model.OvertimeApp;
import jp.co.argo21.nautica.workflow.sample.model.dao.AppTransactionDAO;
import jp.co.argo21.nautica.workflow.sample.model.dao.ApplicationDAO;
import jp.co.argo21.nautica.workflow.sample.model.dao.DAOFactory;
import jp.co.argo21.nautica.workflow.sample.util.Constants;
import jp.co.argo21.nautica.workflow.sample.util.ResourceManager;
import jp.co.argo21.nautica.workflow.sample.util.ServiceAccessor;
import jp.co.argo21.nautica.workflow.sample.util.SingletonServices;
import jp.co.argo21.nautica.workflow.sample.util.StateConstants;
import jp.co.argo21.nautica.workflow.sample.util.StringUtil;
import jp.co.argo21.nautica.workflow.sample.util.WebServiceUtil;
import jp.co.argo21.nautica.workflow.soap.InvalidFilterException;
import jp.co.argo21.nautica.workflow.soap.InvalidSessionException;
import jp.co.argo21.nautica.workflow.soap.WorkItemHandler;
import jp.co.argo21.nautica.workflow.soap.WorkflowEngineHandler;
import jp.co.argo21.nautica.workflow.soap.message.Attribute;
import jp.co.argo21.nautica.workflow.soap.message.Filter;
import jp.co.argo21.nautica.workflow.soap.message.Organization;
import jp.co.argo21.nautica.workflow.soap.message.User;
import jp.co.argo21.nautica.workflow.soap.message.WorkItem;
import jp.co.argo21.nautica.workflow.soap.message.WorkItemState;

/**
 * 申請書の入力を再開する。
 * 
 * @author stokin
 *
 */
public class RestartInput extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
   
	/**
	 * doPostに処理を委譲する。
	 * 
	 * @param req リクエスト
	 * @param res レスポンス
	 * @throws ServletException 発生しない
	 * @throws IOException forwardに失敗した場合
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}  	
	
	/**
	 * 申請書の入力を再開する。
	 * 
	 * @param req リクエスト
	 * @param res レスポンス
	 * @throws ServletException 発生しない
	 * @throws IOException forwardに失敗した場合
	 */
	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		HttpSession session = req.getSession(true);
		ResourceManager rm = ResourceManager.getInstance();
		String sessionID = (String)session.getAttribute("sessionID");
		User user = (User)session.getAttribute("user");
		ServletContext context = getServletContext();
		RequestDispatcher dispatcher = null;
		String path = req.getParameter("screen");
		
		try{	
			if(path.equals("Menu")){
				//Menuから来たときには申請内容入力待ち一覧を表示する
				List<AppTransaction> appTrans = getApplyWaitList(sessionID, user);
				
				//申請可能な申請種別がないときにはその旨表示する
				if(appTrans.size() == 0){
					req.setAttribute("errMsg", rm.getValue("error.nolist"));
				} else {
					req.setAttribute("appTrans", appTrans);	
				}
				dispatcher = context.getRequestDispatcher("/ApplyWaitList.jsp");
				
			} else if (path.equals("ApplyWaitList")){
				//ApplyWaitListから来たときにはそれまでの申請内容を取得して、
				//申請入力画面に遷移する。
				String appID = req.getParameter("appID");
				
				OvertimeApp overtime = getOvertimeApp(appID);
				
				req.setAttribute("overtimeApp", overtime);
				dispatcher = req.getRequestDispatcher("/ApplyInput.jsp");
			}	
		} catch (Exception e){
			// 致命的エラー
			session.invalidate();
			req.setAttribute("errMsg", e.toString());
			req.setAttribute("err", e.getStackTrace());
			dispatcher = context.getRequestDispatcher("/FatalError.jsp");
		}
		dispatcher.forward(req, res);
	}
	
	/**
	 * 申請内容入力待ち申請リストを返す。
	 * 
	 * @param sessionID セッションID
	 * @param user ユーザ
	 * @return 申請内容入力待ち申請リスト
	 * @throws Exception 申請内容入力待ち申請リストの取得に失敗した場合
	 */
	private List<AppTransaction> getApplyWaitList(String sessionID, User user) throws Exception {
		WorkItemHandler wiHandler = ServiceAccessor.getInstance().getWorkItemHandler();
		
		// プロセス変数[状態]が"APPLY_WAIT"である作業項目を取得する
        List<Filter> stateFilter = WebServiceUtil.createEqualAttributeFilter(Constants.STATE, StateConstants.APPLY_WAIT);
        List<WorkItem> itemList = wiHandler.getWorkItems(sessionID, stateFilter);
        
        WorkflowEngineHandler wfEngineHandler = ServiceAccessor.getInstance().getWfEngineHandler();
        List<AppTransaction> appTransList = new ArrayList<AppTransaction>();
        for(WorkItem item : itemList){
        	 //作業項目の申請書番号を取得する
        	 String pid = item.getProcessID();
             Attribute attr 
                 = wfEngineHandler.getProcessAttributeValue(sessionID, pid, Constants.APPLICATION_NO);
            
            //申請書番号を元に申請トランザクションテーブルを検索する
        	AppTransactionDAO appTransDao = DAOFactory.getAppTransactionDAO();
        	AppTransaction appTrans = appTransDao.getAppTransactionForContinue(attr.getValue(), user.getId());
      
        	if (appTrans != null) {
                // ユーザIDからユーザ名を取得してAppTransactionオブジェクトを更新する
                String appUserID = appTrans.getAppUserID();
                User appUser = SingletonServices.getInstance().getUserManager().getUser(appUserID);
                appTrans.setAppUserID(StringUtil.toFullName(appUser));
                appTransList.add(appTrans);
            }
        }
        return appTransList;
	}
	
	/**
	 * 申請内容を返す。
	 * 
	 * @param appID 申請書番号
	 * @return 申請内容
	 * @throws Exception 申請内容の取得に失敗した場合
	 */
	private OvertimeApp getOvertimeApp(String appID) throws Exception{
		ApplicationDAO appDao = DAOFactory.getApplicationDAO();
		Application app = appDao.getApplicationByID(appID);
		return (OvertimeApp)app;
	}
}