/*
 
Copyright (C) 2009 NTT DATA INTELLILINK CORPORATION
 
This program is free software; you can redistribute it and/or
Modify it under the terms of the GNU General Public License 
as published by the Free Software Foundation, version 2.
 
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied 
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
PURPOSE.  See the GNU General Public License for more details.
 
*/

package jp.co.intellilink.operation.logger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;

import javax.ejb.FinderException;
import javax.naming.NamingException;

import org.jboss.aop.Aspect;
import org.jboss.aop.Bind;
import org.jboss.aop.advice.Scope;
import org.jboss.aop.joinpoint.MethodInvocation;

import com.clustercontrol.bean.FacilityTreeItem;
import com.clustercontrol.bean.Property;
import com.clustercontrol.collectiverun.bean.CommandInfo;
import com.clustercontrol.collectiverun.bean.CommandParameterInfo;
import com.clustercontrol.collectiverun.bean.ItemConstant;
import com.clustercontrol.collectiverun.bean.ItemInfo;
import com.clustercontrol.collectiverun.bean.ParameterInfo;
import com.clustercontrol.collectiverun.bean.ParameterSelectInfo;
import com.clustercontrol.collectiverun.bean.TypeInfo;
import com.clustercontrol.collectiverun.ejb.entity.CRunCmdMstLocal;
import com.clustercontrol.collectiverun.ejb.entity.CRunCmdMstUtil;
import com.clustercontrol.collectiverun.factory.ParameterProperty;
import com.clustercontrol.util.Messages;
import com.clustercontrol.util.PropertyUtil;

/**
 * 一括制御機能 操作ログ出力クラス
 * 
 * @since 1.0.0
 * @version 1.0.0
 * @see jp.co.intellilink.operation.logger.Logger
 */
@Aspect (scope= Scope.PER_INSTANCE)
public class CollectiveRun extends Logger {

	/**
	 * マスタアイテム順序変更時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.collectiverun.ejb.session.CollectiveRunControllerBean->changeOrder(..))")
	public Object changeOrderAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[CollectiveRun] Change Order";
		StringBuffer msg = new StringBuffer();

		Object[] args = ((MethodInvocation)invocation).getArguments();
		if(args.length > 0 && args[0] instanceof ItemInfo){
			msg.append(getItemName("", "1", (ItemInfo)args[0]));
		}
		if(args.length > 1 && args[1] instanceof ItemInfo){
			msg.append(getItemName("", "2", (ItemInfo)args[1]));
		}
		if(args.length > 2 && args[2] instanceof ItemInfo){
			msg.append(getItemName("Parent", "", (ItemInfo)args[2]));
		}

		outputLogMessage(title, msg.toString(), invocation);

		return result;
	}

	/**
	 * マスタアイテム更新時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.collectiverun.ejb.session.CollectiveRunControllerBean->updateMaster(..))")
	public Object updateMasterAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[CollectiveRun] Change Item";
		StringBuffer msg = new StringBuffer();

		Object[] args = ((MethodInvocation)invocation).getArguments();
		if(args.length > 0 && args[0] instanceof ItemInfo){
			msg.append(getItemName("", "", (ItemInfo)args[0]));
		}
		if(args.length > 1 && args[1] instanceof ItemInfo){
			msg.append(getItemName("Parent", "", (ItemInfo)args[1]));
		}

		outputLogMessage(title, msg.toString(), invocation);

		return result;
	}

	/**
	 * マスタアイテム削除時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.collectiverun.ejb.session.CollectiveRunControllerBean->deleteMaster(..))")
	public Object deleteMasterAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[CollectiveRun] Delete Item";
		StringBuffer msg = new StringBuffer();

		Object[] args = ((MethodInvocation)invocation).getArguments();
		if(args.length > 0 && args[0] instanceof ItemInfo){
			msg.append(getItemName("", "", (ItemInfo)args[0]));
		}
		if(args.length > 1 && args[1] instanceof ItemInfo){
			msg.append(getItemName("Parent", "", (ItemInfo)args[1]));
		}

		outputLogMessage(title, msg.toString(), invocation);

		return result;
	}

	/**
	 * 実行時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.collectiverun.ejb.session.CollectiveRunControllerBean->run(*.String, *.Property, *.Locale))")
	public Object runAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[CollectiveRun] Run";
		StringBuffer msg = new StringBuffer();

		Object[] args = ((MethodInvocation)invocation).getArguments();
		if(args.length > 0 && args[0] instanceof String){
			msg.append(", TypeID=");
			msg.append((String)args[0]);
		}
		if(args.length > 1 && args[1] instanceof Property){
			ArrayList values = PropertyUtil.getPropertyValue((Property)args[1], ParameterProperty.SCOPE);
			msg.append(", FacilityID=");
			String facilityId = null;
			if(values.get(0) instanceof FacilityTreeItem)
				facilityId = ((FacilityTreeItem)values.get(0)).getData().getFacilityId();
			else if(values.get(0) instanceof String && ((String)values.get(0)).length() > 0)
				facilityId = (String)values.get(0);
			msg.append(facilityId);

			values = PropertyUtil.getPropertyValue((Property)args[1], ParameterProperty.NAME);
			msg.append(", CommandID=");
			String commandId = null;
			if(values.get(0) instanceof String && ((String)values.get(0)).length() > 0)
				commandId = getCommandId((String)args[0], (String)values.get(0), (Locale)args[2]);
			msg.append(commandId);
		}

		outputLogMessage(title, msg.toString(), invocation);

		return result;
	}

	/**
	 * コマンドID取得
	 * 
	 * @param typeId タイプID
	 * @param name 名前
	 * @param locale ロケール
	 * @return コマンドID
	 * @throws FinderException
	 * @throws NamingException
	 */
	protected String getCommandId(String typeId, String name, Locale locale) throws FinderException, NamingException {
		String commandId = null;

		Collection cmdList = CRunCmdMstUtil.getLocalHome().findByTypeId(typeId);

		if(cmdList != null && cmdList.size() > 0){
			Iterator itr = cmdList.iterator();
			while(itr.hasNext()){
				CRunCmdMstLocal cmd = (CRunCmdMstLocal)itr.next();
				String nameValue = Messages.getString(cmd.getName_id(), locale);
				if(nameValue.equals(name)){
					commandId = cmd.getCommand_id();
					break;
				}
			}
		}

		return commandId;
	}

	/**
	 * アイテム名取得
	 * 
	 * @param header ヘッダ文字列
	 * @param footer フッタ文字列
	 * @param info アイテム情報
	 * @return アイテム名
	 */
	protected String getItemName(String header, String footer, ItemInfo info){
		StringBuffer msg = new StringBuffer();
		msg.append(", ");
		msg.append(header);
		if(info.getType() == ItemConstant.TYPE_TYPE){
			msg.append("TypeID");
			msg.append(footer);
			msg.append("=");
			msg.append(((TypeInfo)info).getId());
		}
		else if(info.getType() == ItemConstant.TYPE_COMMAND){
			msg.append("CommandID");
			msg.append(footer);
			msg.append("=");
			msg.append(((CommandInfo)info).getId());
		}
		else if(info.getType() == ItemConstant.TYPE_COMMAND_PARAMETER){
			msg.append("CommandParamID");
			msg.append(footer);
			msg.append("=");
			msg.append(((CommandParameterInfo)info).getId());
		}
		else if(info.getType() == ItemConstant.TYPE_PARAMETER){
			msg.append("ParamID");
			msg.append(footer);
			msg.append("=");
			msg.append(((ParameterInfo)info).getId());
		}
		else if(info.getType() == ItemConstant.TYPE_SELECT_ITEM){
			msg.append("SelectItemID");
			msg.append(footer);
			msg.append("=");
			msg.append(((ParameterSelectInfo)info).getName());
		}
		else{
			return "";
		}
		return msg.toString();
	}
}
