/*
 
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 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.OutputNotifyGroupInfo;
import com.clustercontrol.bean.Property;
import com.clustercontrol.jobmanagement.bean.JobTriggerInfo;
import com.clustercontrol.jobmanagement.bean.JobTriggerTypeConstant;
import com.clustercontrol.jobmanagement.bean.OperationConstant;
import com.clustercontrol.jobmanagement.bean.ScheduleInfo;
import com.clustercontrol.jobmanagement.factory.JobOperationProperty;
import com.clustercontrol.util.PropertyUtil;

/**
 * ジョブ管理機能 操作ログ出力クラス
 * 
 * @since 1.0.0
 * @version 1.0.0
 * @see jp.co.intellilink.operation.logger.Logger
 */
@Aspect (scope= Scope.PER_VM)
public class Job extends Logger {

	/**
	 * スケジュール追加時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.jobmanagement.ejb.session.JobControllerBean->addSchedule(..))")
	public Object addScheduleAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[Job] Add Schedule";
		StringBuffer msg = new StringBuffer();

		Object[] args = ((MethodInvocation)invocation).getArguments();
		if(args.length > 0 && args[0] instanceof ScheduleInfo){
			ScheduleInfo info = (ScheduleInfo)args[0];
			msg.append(", ScheduleID=");
			msg.append(info.getId());
		}

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

		return result;
	}

	/**
	 * スケジュール変更時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.jobmanagement.ejb.session.JobControllerBean->modifySchedule(..))")
	public Object modifyScheduleAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[Job] Change Schedule";
		StringBuffer msg = new StringBuffer();

		Object[] args = ((MethodInvocation)invocation).getArguments();
		if(args.length > 0 && args[0] instanceof ScheduleInfo){
			ScheduleInfo info = (ScheduleInfo)args[0];
			msg.append(", ScheduleID=");
			msg.append(info.getId());
		}

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

		return result;
	}

	/**
	 * スケジュール削除時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.jobmanagement.ejb.session.JobControllerBean->deleteSchedule(..))")
	public Object deleteScheduleAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[Job] Delete Schedule";
		StringBuffer msg = new StringBuffer();

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

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

		return result;
	}

	/**
	 * ジョブ登録時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.jobmanagement.ejb.session.JobControllerBean->registerJob(..))")
	public Object registerJobAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[Job] Set Job";

		outputLogMessage(title, "", invocation);

		return result;
	}

	/**
	 * ジョブ実行時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.jobmanagement.ejb.session.JobControllerBean->runJob(..))")
	public Object runJobAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

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

		Object[] args = ((MethodInvocation)invocation).getArguments();
		if(args.length > 0 && args[0] instanceof String){
			msg.append(", JobID=");
			msg.append((String)args[0]);
		}
		if(args.length == 2){
			if(args[1] instanceof JobTriggerInfo){
				JobTriggerInfo info = (JobTriggerInfo)args[1];
				msg.append(", Trigger=");
				msg.append(triggerTypeToString(info.getTrigger_type()));
			}
		}
		else if(args.length == 3){
			if(args[2] instanceof JobTriggerInfo){
				JobTriggerInfo info = (JobTriggerInfo)args[2];
				msg.append(", Trigger=");
				msg.append(triggerTypeToString(info.getTrigger_type()));
			}
			if(args[1] instanceof OutputNotifyGroupInfo){
				OutputNotifyGroupInfo info = (OutputNotifyGroupInfo)args[1];
				msg.append(", NotifyID=");
				msg.append(info.getNotifyId());
				msg.append(", MonitorID=");
				msg.append(info.getMonitorId());
			}
		}

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

		return result;
	}

	/**
	 * ジョブ操作時のログ出力
	 * 
	 * @param invocation 
	 * @return invokeNext()の結果
	 * @throws Throwable
	 */
	@Bind (pointcut="execution(public void com.clustercontrol.jobmanagement.ejb.session.JobControllerBean->operationJob(..))")
	public Object operationJobAdvice(MethodInvocation invocation) throws Throwable {
		Object result = invocation.invokeNext();

		String title = "[Job] Operate Job";
		StringBuffer msg = new StringBuffer();

		Object[] args = ((MethodInvocation)invocation).getArguments();
		if(args.length > 0 && args[0] instanceof Property){
			ArrayList values = PropertyUtil.getPropertyValue((Property)args[0], JobOperationProperty.SESSION);
			msg.append(", SessionID=");
			msg.append((String)values.get(0));

			values = PropertyUtil.getPropertyValue((Property)args[0], JobOperationProperty.JOB);
			msg.append(", JobID=");
			msg.append((String)values.get(0));

			values = PropertyUtil.getPropertyValue((Property)args[0], JobOperationProperty.FACILITY);
			msg.append(", FacilityID=");
			if(values.size() > 0 && values.get(0) instanceof String && ((String)values.get(0)).length() > 0)
				msg.append((String)values.get(0));

			values = PropertyUtil.getPropertyValue((Property)args[0], JobOperationProperty.CONTROL);
			msg.append(", Operation=");
			if(values.get(0) instanceof String)
				msg.append(getOperationString((String)values.get(0)));

			values = PropertyUtil.getPropertyValue((Property)args[0], JobOperationProperty.END_VALUE);
			msg.append(", EndValue=");
			if(values.size() > 0 && values.get(0) instanceof Integer)
				msg.append(((Integer)values.get(0)).toString());
		}

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

		return result;
	}

	/**
	 * 実行契機の文字列取得
	 * 
	 * @param type 実行契機
	 * @return 実行契機文字列
	 */
	protected String triggerTypeToString(int type){
		if (type == JobTriggerTypeConstant.TYPE_SCHEDULE) {
			return "Schedule";
		} else if (type == JobTriggerTypeConstant.TYPE_MANUAL) {
			return "Manual";
		} else if (type == JobTriggerTypeConstant.TYPE_MONITOR) {
			return "Monitor";
		} 
		return "";
	}

	/**
	 * ログ出力用の操作名取得
	 * 
	 * @param string 操作名(画面表示)
	 * @return ログ出力用操作名
	 */
	public static String getOperationString(String string){
		if(string.equals(OperationConstant.STRING_START_AT_ONCE)){
			return "Start[Start]";
		}
		else if(string.equals(OperationConstant.STRING_START_SUSPEND)){
			return "Start[Cancel Suspend]";
		}
		else if(string.equals(OperationConstant.STRING_START_SKIP)){
			return "Start[Cancel Skip]";
		}
		else if(string.equals(OperationConstant.STRING_START_WAIT)){
			return "Start[Cancel Pause]";
		}
		else if(string.equals(OperationConstant.STRING_STOP_AT_ONCE)){
			return "Stop[Command]";
		}
		else if(string.equals(OperationConstant.STRING_STOP_SUSPEND)){
			return "Stop[Suspend]";
		}
		else if(string.equals(OperationConstant.STRING_STOP_SKIP)){
			return "Stop[Skip]";
		}
		else if(string.equals(OperationConstant.STRING_STOP_WAIT)){
			return "Stop[Pause]";
		}
		else if(string.equals(OperationConstant.STRING_STOP_MAINTENANCE)){
			return "Stop[Change End Value]";
		}
		else if(string.equals(OperationConstant.STRING_STOP_SET_END_VALUE)){
			return "Stop[Set End Value]";
		}
		return "";
	}
}
