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

import java.io.IOException;

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

import jp.co.argo21.nautica.workflow.sample.util.ResourceManager;
import jp.co.argo21.nautica.workflow.sample.util.ServiceAccessor;
import jp.co.argo21.nautica.workflow.soap.ConnectionFailedException;
import jp.co.argo21.nautica.workflow.soap.OrganizationManager;
import jp.co.argo21.nautica.workflow.soap.ServiceAccessorException;
import jp.co.argo21.nautica.workflow.soap.UserManager;
import jp.co.argo21.nautica.workflow.soap.WorkflowException;
import jp.co.argo21.nautica.workflow.soap.WorkflowServiceConnector;
import jp.co.argo21.nautica.workflow.soap.message.Organization;
import jp.co.argo21.nautica.workflow.soap.message.User;

/**
 * ログインする。
 * 
 * @author stokin
 *
 */
public class Login extends HttpServlet {
	/**
	 * doPostに処理を委譲する。
	 * 
	 * @param req リクエスト
	 * @param res レスポンス
	 * @throws ServletException 発生しない
	 * @throws IOException forwardに失敗した場合
	 */
	public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
		doPost(req, res);
	}
	
	/**
	 * ユーザの認証を行う。
	 * 
	 * @param req リクエスト
	 * @param res レスポンス
	 * @throws ServletException 発生しない
	 * @throws IOException forwardに失敗した場合
	 */
	public void doPost(HttpServletRequest req, HttpServletResponse res)
	throws ServletException, IOException {
		ResourceManager rm = ResourceManager.getInstance();
		String userID = req.getParameter("userID");
		String password = req.getParameter("password");
		
		HttpSession session = req.getSession(true);
		ServletContext context = getServletContext();
		RequestDispatcher dispatcher = null;
		try {
			//ワークフローエンジンに接続する
			String sessionID = login(userID, password);
			//ユーザIDからUserとOrganizationを取得する
			User user = prepareUser(userID);
			Organization org = prepareOrganization(user);
			
			//セッションID、User、Organizationをセッションに設定
			session.setAttribute("sessionID", sessionID);
			session.setAttribute("user", user);
			session.setAttribute("org", org);
			dispatcher = context.getRequestDispatcher("/Menu.jsp");
		} catch (ConnectionFailedException e){
			req.setAttribute("errMsg", rm.getValue("error.login"));
			dispatcher = context.getRequestDispatcher("/Login.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 userID ユーザID
	 * @param password パスワード
	 * @return sessionID セッションID
	 * @throws ConnectionFailedException 認証に失敗した場合
	 */
	private String login(String userID, String password) throws ConnectionFailedException{
		WorkflowServiceConnector wfServiceConnector = ServiceAccessor.getInstance().getWfServiceConnector();
		String sessionID = wfServiceConnector.connect(userID, password);
		
		return sessionID;	
	}
	
	
	/**
	 * ユーザを取得する。
	 * 
	 * @param userID ユーザID
	 * @return ユーザ
	 * @throws WorkflowException ユーザの取得に失敗した場合
	 * @throws ServiceAccessorException ワークフローエンジンの接続に失敗した場合
	 */
	private User prepareUser(String userID) throws WorkflowException, ServiceAccessorException{
		UserManager userManager = ServiceAccessor.getInstance().getUserManager();
		User user = userManager.getUser(userID);
		
		return user;
	}
	
	
	/**
	 * 所属組織を取得する。
	 * 
	 * @param user ユーザ
	 * @return 所属組織
	 * @throws WorkflowException
	 * @throws ServiceAccessorException
	 */
	private Organization prepareOrganization(User user) throws WorkflowException, ServiceAccessorException{
		OrganizationManager orgManager = ServiceAccessor.getInstance().getOrganizationManager();
		//ユーザはひとつの組織にのみ所属するため、0番目を決め打ち
		Organization org = orgManager.getOrganizationByUser(user).get(0);
		
		return org;
	}
	
}