/////////////////////////////////////////////////////////////////
//Copyright (C) 2005 NTT CORPORATION.
//
//	学習履歴進捗対比表示機能管理クラス
//
//		変更履歴
//			2005.01.26  新規作成  Katsuhiko.Sakurai(UNITEC)
//
//	機能
//
//	このクラスは学習履歴進捗対比表示機能を管理するクラスです。
//
////////////////////////////////////////////////////////////////
package jp.co.ntt.lms.lo.progress;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import jp.co.ntt.lms.Common.Bean.xmo.Base.BaseVo;
import jp.co.ntt.lms.lo.progress.util.XMOInformationGetter;
import jp.co.ntt.lms.xmo.MenuData;
import jp.co.ntt.lms.xmo.XMOPropertyDef;
import jp.co.ntt.lms.xmo.Base.XMSBaseClient;
import jp.co.ntt.lms.xmo.RoleAssignments.RoleAssignmentsClient;
import jp.co.ntt.lms.xmo.util.DebugLog;


/**
 * 学習履歴進捗対比表示機能を管理するクラスです。
 * 
 * @author Katsuhiko Sakurai (UNITEC)
 * @version 1.0
 */
public class LearningProgressManager {

	private final String ACTION_MAPPING_URI = "../../../LearningProgress.do?";
	private final String URI_PARAMS = "listType={0}&parentID={1}&targetID={2}&loginID={3}";
	private final String MENU_DISPLAY_NAME = "進捗表示";

	private final String CANNOT_DISPLAY_LIST = "-1";
	private final String LIST_TYPE_PEOPLE = "0";
	private final String LIST_TYPE_LO = "1";
	
	private final String GROUP_ROOT_ID = "GR000000";
	private final String LO_ROOT_ID = "LO0";
	private final String LEARNER_LO_ROOT_ID = "lotreeroot";
	private final String GROUP_TREE_ROOT_ID ="grouptreeroot";
	
	// 現在の状態
	private final int CURRENT_STATE_LO_ROOT = 0;
	private final int CURRENT_STATE_LO_CONTAINER = 1;
	private final int CURRENT_STATE_LO_LO = 2;
	private final int CURRENT_STATE_PEOPLE_ROOT = 3;
	private final int CURRENT_STATE_PEOPLE_GROUP = 4;
	private final int CURRENT_STATE_PEOPLE_PEOPLE = 5;
	
	/**
	 * メニューを取得します。
	 * 
	 * @param treeViewType　ツリービュー種別
	 * @param treePath 現在のツリーパス
	 * @param selectedPeopleOrGroupID 選択されているグループIDもしくはユーザID 
	 * @param selectedLOID　選択されているLoID
	 * @param parentID 親ID
	 * @param selectedAuthorityMenu 選択されている初期メニュー
	 * @param loginUserID ログインユーザID　
	 * @return MenuData メニュー情報
	 * @throws Exception
	 */
	public MenuData getMenu( String treeViewType, 
								String treePath, 
								String selectedPeopleOrGroupID,
								String selectedLOID,
								String parentID,
								String selectedAuthorityMenu,
								String loginUserID) throws Exception {
	
		DebugLog.write( this.getClass(), 
				MessageFormat.format(
					"進捗メニュー表示用パラメータ：treeViewType={0},treePath={1},selectedPeopleOrGroupID={2}," +
					"selectedLOID={3},parentID={4},selectedAuthorityMenu={5},loginUserID={6}",
					new String[]{treeViewType,selectedPeopleOrGroupID,selectedLOID,parentID,selectedAuthorityMenu,loginUserID}), 
					DebugLog.ROW );
		
		// リスト種別を取得する
		URLParamaters params = this.getURLParamaters( treeViewType, 
														treePath, 
														selectedPeopleOrGroupID, 
														selectedLOID, 
														parentID,
														selectedAuthorityMenu,
														loginUserID);
		
		// リストが表示できない状態の場合、メニューを表示しない
		if ( params.getListType() == CANNOT_DISPLAY_LIST ) return null;
		
		String url = ACTION_MAPPING_URI;

		url += MessageFormat.format( URI_PARAMS, params.getParamsArray() ); 
		
		DebugLog.write( this.getClass(), "url : " + url, DebugLog.ROW );

		return new MenuData( url, this.MENU_DISPLAY_NAME );
	}
	
	/**
	 * LOプロパティ画面で使用するメニューを取得します。
	 * 
	 * @param baseVo メニュー表示用パラメータ情報
	 * @return MenuData メニュー情報
	 * @throws Exception
	 */
	public MenuData getMenu( BaseVo baseVo) throws Exception {
		
		MenuData menu = this.getMenu(baseVo.getTreeViewType(),
								baseVo.getTreepath(),
								baseVo.getGroupUserId(),
								baseVo.getSelectId(),
								baseVo.getParentID(),
								baseVo.getIniMenu(),
								baseVo.getUserId());
		
		if (menu != null) menu.setTargetWindow("_blank");
		
		return menu;
	}
	
	
	/**
	 * LOの進捗リストを取得します。
	 * 
	 * @param parentID 対象となるLOの親LoID
	 * @param targetUserID 対象となるユーザIDもしくはグループID
	 * @param loginID ログインユーザID
	 * @return List 進捗情報リスト
	 * @throws Exception
	 */
	public List getLOProgressList( String parentID, String targetUserID, String loginID ) throws Exception{
		
		AbstractXMOProgressTreeFactory factory = new LOProgressTreeFactory( parentID, targetUserID, loginID );
		return factory.create().getProgressList();
	}

	/**
	 * ユーザの進捗リストを取得します。
	 * 
	 * @param parentID 対象となる親ユーザIDもしくは親グループID
	 * @param targetLOID 対象となるLoID
	 * @param loginID ログインユーザID
	 * @return List 進捗情報リスト
	 * @throws Exception
	 */
	public List getUserProgressList( String parentID, String targetLOID, String loginID ) throws Exception {
		
		AbstractXMOProgressTreeFactory factory = new PeopleProgressTreeFactory( parentID, targetLOID, loginID );
		return factory.create().getProgressList();
	}
	
	
	/**
	 * 進捗表示用のデータを取得します。
	 * 
	 * @param listType リスト種別　0:ユーザ一覧, 1:Lo一覧
	 * @param parentID　対象となる一覧表示の親LOIDもしくは親ユーザID（グループID）
	 * @param targetID　対象となるLoもしくはユーザのID
	 * @return LearningProgressViewData 進捗表示用データオブジェクト
	 * @throws Exception
	 */
	public LearningProgressViewData getLearningProgressViewData(String listType, 
																	String parentID,
																	String targetID,
																	String loginID) throws Exception {
		
		String targetName = null;
		List progressList = null;
		
		// リスト種別がユーザ一覧ならユーザの進捗リストを取得する
		if ( listType.equals(LIST_TYPE_PEOPLE) ) {
			
			targetName = XMOInformationGetter.getLO( targetID ).getLoTytle();
			progressList = this.getUserProgressList(parentID,targetID, loginID);
			
		// リスト種別がLO一覧ならLOの進捗リストを取得する
		} else {

			if ( targetID.startsWith("PE") ) {
				targetName = XMOInformationGetter.getPeople(targetID).getUserName();
			} else {
				targetName = XMOInformationGetter.getGroup(targetID).getGroupName();
			}
			
			progressList = this.getLOProgressList(parentID, targetID, loginID);
		}
		
		// 表示用進捗データオブジェクトを生成し返却する
		return new LearningProgressViewData(listType, targetName, progressList );  
	}
	
	
	/**
	 * 進捗表示メニュー用のGETパラメータを取得します。
	 * 
	 * @param treeViewType　ツリービュー種別
	 * @param treePath 現在のツリーパス
	 * @param selectedPeopleOrGroupID 選択されているグループIDもしくはユーザID 
	 * @param selectedLOID　選択されているLoID
	 * @param parentID 親ID
	 * @param selectedAuthorityMenu 選択されている初期メニュー
	 * @param loginUserID ログインユーザID　
	 * @return URLParamaters URLパラメータ情報
	 * @throws Exception
	 */
	protected URLParamaters getURLParamaters( String treeViewType, 
												String treePath, 
												String selectedGroupOrPeopleID, 
												String selectedLOID, 
												String parentID,
												String selectedAuthorityMenu,
												String loginUserID) throws Exception {
		
		// 権限絞込みメニューで絞り込まれていた場合、進捗表示メニューを表示しない
		//if (selectedAuthorityMenu.length() != 0) return new URLParamaters(CANNOT_DISPLAY_LIST,"","");
		
		// 現在の状態を取得する
		int currentState = this.getCurrentState( treeViewType, treePath );
		if (currentState <  0 ) return new URLParamaters(CANNOT_DISPLAY_LIST,"","","");
		
		DebugLog.write( this.getClass(), "基本画面状態 : " + String.valueOf(currentState), DebugLog.ROW );
		
		List xmoClassNameList = new ArrayList(
				Arrays.asList(new String[]{ XMOPropertyDef.LEARN_XMO, XMOPropertyDef.LOG_XMO }));
		
		switch (currentState) {
        // ■　ユーザルート選択状態 
		case CURRENT_STATE_PEOPLE_ROOT:
        // ■　グループ選択状態 
		case CURRENT_STATE_PEOPLE_GROUP:
        // ■　ユーザ選択状態 
		case CURRENT_STATE_PEOPLE_PEOPLE:
		
			// ユーザが選択されている場合に選択されたユーザの進捗を表示
			if ( selectedGroupOrPeopleID.startsWith("PE") ) {

				// ログインユーザにログ参照権限がない場合はメニューなし
				if ( this.hasAuthority(loginUserID, treeViewType, XMOPropertyDef.LOG_XMO) == false ) {
					DebugLog.write( this.getClass(), "ログ参照権限なし : ", DebugLog.ROW );
					break;
				}

				// ユーザが表示されている状態でクリックがあった場合はメニューなし
				if ( currentState == CURRENT_STATE_PEOPLE_PEOPLE) {
					break;
				}

				return new URLParamaters(LIST_TYPE_LO, LO_ROOT_ID, selectedGroupOrPeopleID, loginUserID);
			} 
			
			// LOが選択されている場合に選択されたLOの進捗を表示
			if ( selectedLOID != null && selectedLOID.length() != 0 ) {
				String parentGroupOrPeopleID = this.getParentIDFromTreePath(treePath);
				
				// ログインユーザにログ参照権限がない場合はメニューなし
				if ( this.hasAuthority(loginUserID, selectedLOID, treeViewType, XMOPropertyDef.LOG_XMO) == false ) {
					DebugLog.write( this.getClass(), "ログ参照権限なし : ", DebugLog.ROW );
					break;
				}

				return new URLParamaters(LIST_TYPE_PEOPLE, 
						parentGroupOrPeopleID.length() == 0 ? GROUP_ROOT_ID : parentGroupOrPeopleID, 
					    selectedLOID, loginUserID );
			}
			
			break;
		
        // ■　LOルート選択状態 
		case CURRENT_STATE_LO_ROOT:
			
			// ユーザが選択されている場合はメニューを表示しない
			if (selectedGroupOrPeopleID != null 
					&& ( selectedGroupOrPeopleID.startsWith("PE") 
							|| selectedGroupOrPeopleID.startsWith("GR") ) ) {
				break;
			}

			// 一覧がLOタブの場合ユーザの進捗を表示
			// ログインユーザに学習権限がある場合に進捗表示
			if (this.hasAuthority(loginUserID, treeViewType, XMOPropertyDef.LEARN_XMO)) {
				return new URLParamaters(LIST_TYPE_LO,
											selectedLOID.length() == 0 ? LO_ROOT_ID : selectedLOID,
													loginUserID, loginUserID);
			}
			break;
		
        // ■　コンテナ選択状態 
		case CURRENT_STATE_LO_CONTAINER:
        // ■　LO選択状態 
		case CURRENT_STATE_LO_LO:

			// ユーザが選択されている場合は選択状態のLO配下の指定されたユーザの進捗を表示する
			if (selectedGroupOrPeopleID != null 
					&& ( selectedGroupOrPeopleID.startsWith("PE") 
							|| selectedGroupOrPeopleID.startsWith("GR") ) ) {
				
				// ログインユーザにログ参照権限がない場合はメニューなし
				if ( this.hasAuthority(loginUserID, treeViewType, XMOPropertyDef.LOG_XMO) == false ) {
					break;
				}

				return new URLParamaters(LIST_TYPE_PEOPLE,
											selectedGroupOrPeopleID,
											selectedLOID.length() == 0 ? LO_ROOT_ID : selectedLOID,
													loginUserID
										);
			}

			// 一覧がLOタブの場合ユーザの進捗を表示
			// ログインユーザに学習権限がある場合に進捗表示
			if (this.hasAuthority(loginUserID, selectedLOID, treeViewType, XMOPropertyDef.LEARN_XMO)) {
				return new URLParamaters(LIST_TYPE_LO,
											selectedLOID.length() == 0 ? LO_ROOT_ID : selectedLOID,
													loginUserID,
													loginUserID);
			}
			
			break;
		}
		
		return new URLParamaters(CANNOT_DISPLAY_LIST,"","","");
	}
	
	/**
	 * 現在の基本画面の表示状態を取得します。
	 * 
	 * @param treeViewType ツリー種別
	 * @param treePath ツリーパス
	 * @return int 現在の基本画面状態
	 * @throws Exception
	 */
	protected int getCurrentState( String treeViewType, String treePath ) throws Exception {

		String currentState = this.getParentIDFromTreePath(treePath);

		// 現在の状態がroot以外の場合
		// TreePathから現在の状態を取得する
		if ( currentState.length() != 0 ) {
			
			// ユーザRoot
			if ( currentState.equals(GROUP_ROOT_ID) || currentState.equals(GROUP_TREE_ROOT_ID) ) {
				return CURRENT_STATE_PEOPLE_ROOT;
			}
			
			// LOルート
			if ( currentState.equals(LO_ROOT_ID) || currentState.equals(LEARNER_LO_ROOT_ID)) {
				return CURRENT_STATE_LO_ROOT;
			}
			
			// 現在の状態がユーザの場合
			if (currentState.startsWith("PE") ) {
				return CURRENT_STATE_PEOPLE_PEOPLE;
			
			// 現在の状態がグループの場合
			} else if (currentState.startsWith("GR") ) {
				return CURRENT_STATE_PEOPLE_GROUP;

			// 現在の状態がLOの場合
			} else {

				// LOタイプを取得
				String loType = XMOInformationGetter.getLO( currentState ).getLoType();
				
				// LOタイプが0ならコンテナ
				if (loType.equals("0")) {
					return CURRENT_STATE_LO_CONTAINER;
				} else {
					return CURRENT_STATE_LO_LO;
				}
			}
			
		} else {
			// 現在状態が取得できなければエラー
			return -1;
		}
	}

	/**
	 * ツリーパスから親IDを取得します。
	 * 
	 * @param treePath ツリーパス
	 * @return String 親ID
	 */
	private String getParentIDFromTreePath(String treePath) {
		
		String[] treeArray = treePath.split("/");

		if ( treeArray.length == 0 ) {
			return "";
		} else {
			return treeArray[ treeArray.length -1 ];
		}
	}
	
	/**
	 * 指定されたユーザに指定された権限があるかどうかを取得します。
	 * 
	 * @param userID ユーザID
	 * @param treeViewType ツリー種別
	 * @param xmoClassName 権限
	 * @return boolean 指定された権限があるかどうか True:権限がある
	 * @throws Exception
	 */
	private boolean hasAuthority( String userID, 
			String treeViewType, 
			String xmoClassName ) throws Exception {
		
		return this.hasAuthority(userID, null, treeViewType, 
				new ArrayList(Arrays.asList(new String[]{xmoClassName})) );
	}
	
	/**
	 * 指定されたユーザに指定されたLOに対して指定された権限があるかどうかを取得します。
	 * 
	 * @param userID ユーザID
	 * @param targetLoID　LoID
	 * @param treeViewType ツリー種別
	 * @param xmoClassName 権限
	 * @return boolean 指定された権限があるかどうか True:権限がある
	 * @throws Exception
	 */
	private boolean hasAuthority( String userID, 
			String targetLoID, 
			String treeViewType,
			String xmoClassName) throws Exception {
		
		return this.hasAuthority(userID, targetLoID, treeViewType,
				new ArrayList(Arrays.asList(new String[]{xmoClassName})) );
	}

	/**
	 * 指定されたユーザに指定されたLOに対して指定された権限があるかどうかを取得します。
	 * 
	 * @param userID ユーザID
	 * @param targetLoID　LoID
	 * @param treeViewType ツリー種別
	 * @param List 権限リスト
	 * @return boolean 指定された権限があるかどうか True:権限がある
	 * @throws Exception
	 */
	private boolean hasAuthority( String userID, 
									String targetLoID, 
									String treeViewType,
									List xmoClassNameList ) throws Exception {
		
		//ルートユーザなら無条件OK
		if (userID.equals("PE000000")) return true;
		
		try{
			//ユーザに割り当てられているXmoIDリストの取得
			ArrayList roleList = this.getAssignXmoList(userID, targetLoID);

			XMSBaseClient xmsBaseClient = new XMSBaseClient();
	
			//検索条件の設定
			//xmsBaseClient.setWhereTreeViewType(treeViewType);
	
			//実行できるXMOリストを取得
			if (xmsBaseClient.select() == false) {
				throw new Exception("select Method of XMSBaseClient Class returned false.");
			}
	
			while (xmsBaseClient.next()) {
				String xmoId = xmsBaseClient.getXmoID();		//xmoId
				String className = xmsBaseClient.getClassName();//実行クラス名
	
				// ユーザが実行できるXMOListに画面で表示できるXMOが含まれていない場合処理なし
				if(roleList.contains(xmoId) == false) continue;
	
				//指定権限があればTrueを返す
				if (className != null 
						&& className.length() != 0 
						&& xmoClassNameList.contains(className)) {
					return true;
				}
	
			}
			return false;

		} catch(Exception e) {
			DebugLog.write( this.getClass(), "権限取得エラー："+ e.getMessage(), DebugLog.MID );
			throw e;
		}
	}
	
	/**
	 * ユーザID、選択したIDを元にユーザに割り当てられているXmoIDリストを取得します。
	 * 
	 * @param userId ユーザID
	 * @param selectId 選択されたID
	 * @return ArrayList ユーザに割り当てられているXmoIDのリスト
	 */
	private ArrayList getAssignXmoList(String userId, String selectId)throws Exception {

		// 権限割当からユーザに割り当てられている権限を取得する
		RoleAssignmentsClient roleAss = new RoleAssignmentsClient();

		// searchXmoListメソッドの第２引数は選択対象がLOの場合はnullを入力パラメータとする
		if ((roleAss.searchXmoList(
				userId,
				((selectId != null && selectId.indexOf("LO") == -1)) ? selectId : null))
			== false) {
			//検索失敗
			throw new Exception("searchXmoList Method of RoleAssignmentsClient Class returned false.");
		}

		//getXmoListの戻りがString[]なのでArryListに変換して返却
		return new ArrayList(Arrays.asList(roleAss.getXmoList()));
	}

	/**
	 * 進捗表示メニュー用URLパラメータクラスです。
	 * 
	 * @author Katsuhiko Sakurai (UNITEC)
	 * @version 1.0
	 */
	public class URLParamaters {

		private String listType = null;
		private String parentID = null;
		private String targetID = null;
		private String loginID = null;
		
		/**
		 * コンストラクタです。
		 * 
		 * @param listType 表示するリストの種別 0:ユーザ一覧, 1:Lo一覧
		 * @param parentID 一覧表示する親ID（Loもしくはユーザ・グループ）
		 * @param targetID 進捗表示対象となるLoIDもしくはユーザ・グループID
		 * @param loginID ログインユーザID
		 */
		public URLParamaters( String listType, String parentID, String targetID, String loginID ) {
			this.listType = listType;
			this.parentID = parentID;
			this.targetID = targetID;
			this.loginID = loginID;
		}
		
		/**
		 * リスト種別を取得します。
		 * 
		 * @return String リスト種別
		 */
		public String getListType() {
			return this.listType;
		}
		
		/**
		 * 親IDを取得します。
		 * 
		 * @return String 親ID
		 */
		public String getParentID() {
			return this.parentID;
		}
		
		/**
		 * 対象IDを取得します。
		 * 
		 * @return String 対象となるID
		 */
		public String getTargetID() {
			return this.targetID;
		}
		
		/**
		 * ログインユーザIDを取得します。
		 * 
		 * @return String ログインユーザID
		 */
		public String getLoginID() {
			return this.loginID;
		}
		
		
		/**
		 * パラメータを配列として取得します。
		 * 
		 * @return String[] パラメータの配列
		 */
		public String[] getParamsArray() {
			return new String[]{ String.valueOf(this.listType), this.parentID, this.targetID, this.loginID };
		}
	}
}
