/*
 * 作成日: 2005/10/20
 *
 * TODO この生成されたファイルのテンプレートを変更するには次へジャンプ:
 * ウィンドウ - 設定 - Java - コード・スタイル - コード・テンプレート
 */
package jp.co.ntt.lms.otm.util;

import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

import jp.co.ntt.lms.otm.sheet.SheetInfo;
import jp.co.ntt.lms.xmf.xmo.Base.Common;
import jp.co.ntt.lms.xmo.Assignments.AssignmentsClient;
import jp.co.ntt.lms.xmo.GroupAndPeople.GroupAndPeopleClient;
import jp.co.ntt.lms.xmo.Groups.GroupsClient;
import jp.co.ntt.lms.xmo.Lo.LoClient;
import jp.co.ntt.lms.xmo.LoRelation.LoRelationClient;
import jp.co.ntt.lms.xmo.Method.MethodClient;
import jp.co.ntt.lms.xmo.Method.MethodData;

/**
 * 
 * OTM でよく使用する処理を集めたユーティリティクラス
 * 
 * @author yasu
 *
 */
public class OTMUtil
{

	/**
	 * LOIDで指定されたメソッド配下のメソッド(親のLOはメソッドという前提)を
	 * Vector に入れて返却する。
	 * 返却値は MethodData(jp.co.ntt.lms.xmo.Method.MethodData) からなる Vector である。
	 * 
	 * @param loID
	 * @return
	 * @throws Exception
	 */
	public static Vector getChildMethodList(String loID) throws Exception
	{
		Vector methodList = new Vector();
		
		MethodClient objXmo = new MethodClient();
		objXmo.setLoID(loID); // 親メソッドのLOIDを指定する。
		//並び順にソートする
		objXmo.setOrderBy(LoRelationClient.TABLE_NAME + "." + LoRelationClient.SORT_NO);
		if(objXmo.getChildMethodList()) {
			while(objXmo.next()) {
				MethodData objData = objXmo.getMethodData();
				if(objData == null) break;
				methodList.add(objData);
			}
		}
		
		return methodList;
	}


	/**
	 * LOIDで指定されたメソッド配下のメソッド(親のLOはメソッドという前提)を
	 * Vector に入れて返却する。
	 * なお、キーワードがkeywordに該当するもののみを返却する
	 * 返却値は MethodData(jp.co.ntt.lms.xmo.Method.MethodData) からなる Vector である。
	 * 
	 * 
	 * @param loID,keyword
	 * @return
	 * @throws Exception
	 */
	public static Vector getChildMethodList(String loID, String keyword) throws Exception
	{
		// 20051208 O.Takeuchi added.
		//
		Vector methodList = new Vector();
		
		MethodClient objXmo = new MethodClient();
		objXmo.clear();		
		objXmo.setLoID(loID); // 親メソッドのLOIDを指定する。
		objXmo.setWhereString(LoClient.KEYWORD , "=", keyword);
		//並び順にソートする
		objXmo.setOrderBy(LoRelationClient.TABLE_NAME + "." + LoRelationClient.SORT_NO);
		if(objXmo.getChildMethodList()) {
			while(objXmo.next()) {
				MethodData objData = objXmo.getMethodData();
				if(objData == null) break;
				methodList.add(objData);
			}
		}
		
		return methodList;
	}
	
	/**
	 * 指定したLOID を持つメソッドLOのデータを取得する。
	 * 見つかれなければ、null を返却する。
	 * 
	 * @param loID
	 * @return
	 * @throws Exception
	 */
	public static MethodData getMethodData(String loID) throws Exception
	{
		MethodClient client = new MethodClient();
		client.clear();
		client.setWhereLoID(loID);
		client.select();
		if (client.next())
		{
			return client.getMethodData();
		}
		else
		{
			return null;
		}
	}
	
	/**
	 * 指定したメソッドLOのMethodLOID を取得する。
	 * 指定したLOID のメソッドLOが見つかれない場合、null を返却する。
	 * 
	 * @param loID
	 * @return
	 * @throws Exception
	 */
	public static String getMethodLOID(String loID) throws Exception
	{
		MethodData data = getMethodData(loID);
		if (data != null)
		{
			return data.getMethodLOID();
		}
		else
		{
			return null;
		}
	}
	
	/**
	 * 指定されたLOのマテリアルIDを取得する。
	 * (複数のLOの子になっている場合のみ、１以上のマテリアルIDが返却される。)
	 * 
	 * @param loID
	 * @return
	 * @throws Exception
	 */
	public static Vector getMaterialID(String loID) throws Exception {
		Vector	vcMaterialID = new Vector();
		LoRelationClient lrc = new LoRelationClient(); 
		lrc.setWhereChildID(loID);
		lrc.select();
		while( lrc.next() )
		{
			String strMaterialID = lrc.getmaterialID();
			vcMaterialID.add(strMaterialID);
		}
		return vcMaterialID;
	}
	
	/**
	 * 指定されたグループの上位グループのうち、指定されたLOが学習アサインされた
	 * 最上位のグループのグループIDを取得する。
	 * 
	 * 見つからなかった場合は、null が返却される。
	 * 
	 * @param groupID
	 * @param loID
	 * @return
	 * @throws Exception
	 */
	public static String getAssigneeTopGroupID(String groupID, String loID) throws Exception
	{
		String materialID = null;
		Vector materialVector = getMaterialID(loID);
		if (materialVector.size() < 1)
		{
			throw new Exception("LOID " + loID + " のマテリアルIDが取得できません。");
		}
		materialID = (String)materialVector.get(0);
		
		String childID = null;
		String parentID = groupID;
		
		String result = null;
		AssignmentsClient assignClient = new AssignmentsClient();
		while (!parentID.equals(Common.GROUP_ROOT))
		{
			childID = groupID;
			groupID = parentID;
			parentID = getParentGroupID(groupID);
			
			//このグループに対して指定したLOが学習アサインされているか
			assignClient.clear();
			assignClient.setWhereLearnAuthority();
			assignClient.setMaterialID(materialID);
			assignClient.setWhereMemberShipID(parentID + groupID);
			assignClient.select();
			if (!assignClient.next())
			{
				//学習アサインされていない
				//この時点での childID の値が取得すべきグループID
				result = childID;
				break;
			}
			else
			{
				//学習アサインされている
				result = groupID;
			}
		}
		
		return result;
	}

	/**
	 * 指定されたグループ の親グループのID を取得する。
	 * 親がない場合、null を返却する。
	 * 
	 * @param groupID グループID
	 * @return
	 * @throws Exception
	 */
	public static String getParentGroupID(String groupID) throws Exception
	{
		GroupAndPeopleClient client = new GroupAndPeopleClient();
		client.setWhereChildID(groupID);
		client.select();
		if (client.next())
		{
			return client.getParentID();
		}
		else
		{
			return null;
		}
	}
	
	/**
	 * 指定されたLOの親LOのLOIDを取得する。
	 * 見つからない場合、null が返却される。
	 * 
	 * @param loID
	 * @return
	 * @throws Exception
	 */
	public static String getParentLOID(String loID) throws Exception
	{
		LoRelationClient client = new LoRelationClient();
		client.clear();
		client.setWhereChildID(loID);
		client.select();
		if (client.next())
		{
			return client.getParentID();
		}
		else
		{
			return null;
		}
	}

	/**
	 * 指定されたLOのマテリアルIDのリストを取得する。
	 * (複数のLOの子になっている場合のみ、１以上のマテリアルIDが返却される。)
	 * 
	 * @param loID
	 * @return
	 * @throws Exception
	 */
	public static Vector getMaterial(String loID) throws Exception {
		Vector	vcMaterialID = new Vector();
		LoRelationClient lrc = new LoRelationClient(); 
		lrc.setWhereChildID(loID);
		lrc.select();
		while( lrc.next() ) {
			String strMaterialID = lrc.getmaterialID();
			vcMaterialID.add(strMaterialID);
		}
		return vcMaterialID;
	}

	/**
	 * 指定されたグループの外部ID を取得する。
	 * 
	 * 見つからなかった場合は、null が返却される。
	 * 
	 * @param loID
	 * @return
	 */
	public static String getGroupForeignID(String groupID) throws Exception
	{
		String foreignID = null;
		GroupsClient gClient = new GroupsClient();
		gClient.setWhereGroupID(groupID);
		if (gClient.select())
		{
			if (gClient.next())
			{
				foreignID = gClient.getForeignID();
			}
		}
		gClient = null;
		
		return foreignID;
	}
	
	/**
	 * 指定されたユーザーまたはグループがどのグループに所属するかを示す
	 * メンバーシップ情報を含んだ Hashtable を取得する。
	 * 
	 * メンバーシップID をキーとし、グループID を値とする Hashtable を
	 * 返却する。
	 * 
	 * @param childID    ユーザーID または グループID を指定する。
	 * @return
	 * @throws Exception
	 */
	public static Hashtable getMembershipHash(String childID) throws Exception
	{
		Hashtable membershipHash = new Hashtable();

		GroupAndPeopleClient gapc = new GroupAndPeopleClient(); 
		gapc.setWhereChildID(childID);
		gapc.select();
		while( gapc.next() )
		{
			String strMembershipID = gapc.getMemberShipID();
			//vcMembership.add(strMembershipID);
			if (!membershipHash.containsKey(strMembershipID))
			{
				membershipHash.put(strMembershipID, gapc.getParentID());
			}
		}
		
		return membershipHash;
	}

	/**
	 * 指定されたグループ直下のメンバーシップ情報を含んだ Hashtable を取得する。
	 * 
	 * メンバーシップID をキーとし、ユーザーID または グループID を値とする
	 * Hashtable を返却する。
	 * 
	 * @param parentID    グループID を指定する。
	 * @return
	 * @throws Exception
	 */
	public static Hashtable getChildMembershipHash(String parentID) throws Exception
	{
		Hashtable membershipHash = new Hashtable();

		GroupAndPeopleClient gapc = new GroupAndPeopleClient();
		gapc.clear();
		gapc.setWhereParentID(parentID);
		gapc.select();
		while( gapc.next() )
		{
			String strMembershipID = gapc.getMemberShipID();
			if (!membershipHash.containsKey(strMembershipID))
			{
				membershipHash.put(strMembershipID, gapc.getChildID());
			}
		}
		
		return membershipHash;
	}

	/**
	 * 指定されたユーザーの指定されたLOのステータスを取得する。
	 * 
	 * @param userID
	 * @param loID
	 * 
	 * @return
	 * @throws Exception
	 */
	public static int getLOStatus(String userID, String loID) throws Exception
	{
		LoClient lo = new LoClient();
		int status = 0;
		if( !lo.checkStatus(loID, userID) )
		{
			throw new Exception(lo.getMessage());
		}
		status = lo.getStatus();
		
		return status;
	}


	/**
	 * 指定されたメンバーシップID からグループID を取得する。
	 * メンバーシップID は 返却されるグループのメンバーシップを示すID。
	 * 
	 * @param membershipID
	 * @return
	 */
	public static String getGroupID(String membershipID)
	{
		if (membershipID != null)
		{
			return membershipID.substring(0, 8);
		}
		else
		{
			return null;
		}
	}

	/**
	 * 指定されたグループIDのグループ名を返す。
	 * @param strGroupID グループID。
	 * @return グループ名。指定されたグループIDのグループが存在しないときは null。
	 * @throws Exception
	 */
	public static String getGroupName(String strGroupID)
		throws Exception
	{
		// クライアントのインスタンス化
		GroupsClient objClient = new GroupsClient();
		
		// グループIDを検索条件に設定する
		objClient.setWhereGroupID(strGroupID);
		
		// 検索実行
		if (objClient.select() == false)
		{
			throw new Exception(objClient.getMessage());
		}
		
		if (objClient.next() == true)
		{
			return objClient.getGroupName();
		}
		
		return null;
	}
	
	/**
	 * 指定されたメンバーシップID と マテリアルID のアサイン情報を
	 * Hashtable に格納して返却する。
	 * 
	 * assignid : アサインID
	 * study_start_date
	 * enddate
	 * assigner
	 * learn_authority
	 * management_authority
	 * opening_date
	 * closing_date
	 * study_limit_count
	 * study_count
	 * method_flag
	 * 
	 * @param membershipID
	 * @param materialID
	 * @return
	 * @throws Exception
	 */
	public static Hashtable getAssignData(String membershipID, String materialID) throws Exception
	{
	    Hashtable result = null;
	    
	    AssignmentsClient client = new AssignmentsClient();
	    client.setWhereMemberShipID(membershipID);
	    client.setWhereMaterialID(materialID);
	    
	    if (client.select() == false)
	    {
	        throw new Exception(client.getMessage());
	    }
	    
	    if (client.next())
	    {
	        result = new Hashtable();
	        putToHash("assignid", client.getAssignID(), result);
	        putToHash("study_start_date", client.getStudyStartDate(), result);
	        putToHash("enddate", client.getEndDate(), result);
	        putToHash("assigner", client.getAssigner(), result);
	        putToHash("learn_authority", client.getLearnAuthority(), result);
	        putToHash("management_authority", client.getManagementAuthority(), result);
	        putToHash("opening_date", client.getOpeningDate(), result);
	        putToHash("closing_date", client.getClosingDate(), result);
	        putToHash("study_limit_count", client.getStudyLimitCount(), result);
	        putToHash("study_count", client.getStudyCount(), result);
	        putToHash("method_flag", client.getMethodFlag(), result);
	    }
	    
	    return result;
	}
	
	private static void putToHash(String key, Object value, Hashtable hash)
	{
	    if (value != null)
	    {
	        hash.put(key, value);
	    }
	}
	
	/**
	 * シート情報取得
	 * 
	 * @param userId
	 * @param sheetType
	 * @param methodId
	 * @param sheetLoID
	 * @return
	 * @throws Exception
	 */
	public static SheetInfo getSheetInfo(String userId, String sheetType, String methodId, String sheetLoID)
		throws Exception {
		System.out.println("userId : " + userId);
		System.out.println("sheetType : " + sheetType);
		System.out.println("methodId : " + methodId);
		System.out.println("sheetLoID : " + sheetLoID);
		
		
		SheetInfo sheetInfo = new SheetInfo();
		sheetInfo.setUserId(userId);
		sheetInfo.setMethodId(methodId);
		sheetInfo.setSheetLoID(sheetLoID);
		sheetInfo.setSheetType(sheetType);
		
		// materialId取得
		String materialId = null;
		String childLoID = sheetLoID;
		String parentLoID = getParentLOID(childLoID);
		while (parentLoID != null) {
			materialId = parentLoID + childLoID;
			System.out.println("materialId : " + materialId);
			
			childLoID = parentLoID;
			parentLoID = getParentLOID(childLoID);
		}
		
		// membershipId 取得
		Hashtable memberships = getMembershipHash(userId);
		for (Iterator it = memberships.keySet().iterator(); it.hasNext();) {
			String membership = (String)it.next();
			System.out.println("membership : " + membership);
			
			// アサイン情報取得
			Hashtable assignData = getAssignData(membership, materialId);
			if (assignData == null) continue;
			
			sheetInfo.setOpeningDate((Date)assignData.get("opening_date"));
			sheetInfo.setClosingDate((Date)assignData.get("closing_date"));
			sheetInfo.setAssignId((String)assignData.get("assignid"));
			break; // 1行目のみ
		}
		
		return sheetInfo;
	}
}
