package com.zi.mwms.solution.event.user;

import java.sql.Timestamp;
import java.util.Calendar;


import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.cim.idm.framework.exception.ext.DuplicateNameSignal;
import com.cim.idm.framework.exception.ext.FrameworkErrorSignal;
import com.cim.idm.framework.exception.ext.InvalidStateTransitionSignal;
import com.cim.idm.framework.exception.ext.NotFoundSignal;
import com.cim.idm.wmsextend.generic.GenericServiceProxy;
import com.cim.idm.wmsextend.generic.errorHandler.CustomException;
import com.cim.idm.wmspackage.user.UserServiceProxy;
import com.cim.idm.wmspackage.user.management.data.UserGroup;
import com.cim.idm.wmspackage.user.management.data.UserGroupKey;
import com.cim.idm.wmspackage.user.management.data.UserInfo;
import com.cim.idm.wmspackage.user.management.data.UserInfoKey;
import com.cim.idm.wmspackage.user.management.data.UserLoggedIn;
import com.cim.idm.wmspackage.user.management.data.UserLoggedInHistory;
import com.cim.idm.wmspackage.user.management.data.UserLoggedInHistoryKey;
import com.cim.idm.wmspackage.user.management.data.UserLoggedInKey;
import com.cim.idm.wmspackage.user.management.impl.EncryptUtil;


public class UserProfileServiceImpl implements ApplicationContextAware{
	/**
	 * @uml.property  name="applicationContext"
	 * @uml.associationEnd
	 */
	private ApplicationContext     	applicationContext;
	private static Log 				log = LogFactory.getLog(UserProfileServiceImpl.class);

	/**
	 * @param arg0
	 * @throws BeansException
	 * @uml.property  name="applicationContext"
	 */
	public void setApplicationContext(ApplicationContext arg0)throws BeansException
	{
			applicationContext = arg0;
	}


	public void login(String userId,
				  	  String password,
					  String uiName,
					  String workStationName,
					  String shopName,
					  String uiVersion,
					  String deamon)
	throws com.cim.idm.framework.exception.ext.InvalidStateTransitionSignal, FrameworkErrorSignal, NotFoundSignal, DuplicateNameSignal, Exception
	{

		UserInfo userInfoData = this.verifyUser(userId);

		if (StringUtils.isEmpty(userInfoData.getUserGroupName()))
		{
			throw new CustomException("User-0006", userId, userInfoData.getUserGroupName());
		}

		this.verifyUserGroupAccessFactory(userInfoData, shopName);

		this.verifyPassword(userId, password);

//		if(uiName.equals("OIC"))
		{
			try
			{
				OICLogIn(userId, password, uiName, workStationName, uiVersion, deamon);
			}
			catch ( Exception e)
			{
				log.error(e);

				try
				{
					OICLogOut(userId, uiName);
				}
				catch (Exception ex)
				{
					log.error(ex);
				}

				OICLogIn(userId, password, uiName, workStationName, uiVersion, deamon);
			}
		}
//		else
//		{
//			try
//			{
//				UserServiceProxy.getUserInfoService().logIn(userId, password, uiName, workStationName);
//			}
//			catch ( Exception e)
//			{
//				log.error(e);
//				this.logOut(userId, uiName, workStationName);
//
//				UserServiceProxy.getUserInfoService().logIn(userId, password, uiName, workStationName);
//			}
//		}
	}

	public void OICLogIn(String userId, String password, String uiName, String workstationName, String uiVersion, String deamon)
			throws FrameworkErrorSignal, NotFoundSignal, DuplicateNameSignal, CustomException
	{
		// 1. Check if password is correct
		UserInfo UserInfo = UserServiceProxy.getUserInfoService().selectByKey(new UserInfoKey(userId));
		String encryptedPassword = EncryptUtil.encrypt(password);
		if (StringUtils.equals(UserInfo.getPassword(), encryptedPassword) == false)
		{
			throw new CustomException("User-0002", new Object[] { userId, password });
		}

		// 2. Check the user already is log in
		UserLoggedInKey userLoggedInKey = new UserLoggedInKey(userId, uiName);
		UserLoggedIn userLoggedIn = null;
		try
		{
			userLoggedIn = UserServiceProxy.getUserLoggedInService().selectByKey(userLoggedInKey);
			if (StringUtils.equalsIgnoreCase(userLoggedIn.getWorkStationName(), workstationName) == false)
			{
				// if WorkStation is wrong, in another WorkStation logged in already.
				throw new CustomException("User-0001", new Object[] { userId });
			}
		}
		catch (NotFoundSignal e)
		{
			// can not throw Exception .For if no data in  UserLoggedIn table, it means not exisit current log in user.
		}

		// 2. Update or Insert UserLoggedIn
		if (userLoggedIn != null)
		{
			userLoggedIn.setLoggedInTime(new Timestamp(System.currentTimeMillis()));
			userLoggedIn.setLoggedInUiVersion(uiVersion);
			userLoggedIn.setDeamon(deamon);
			UserServiceProxy.getUserLoggedInService().update(userLoggedIn);
		}
		else
		{
			userLoggedIn = new UserLoggedIn(userLoggedInKey, workstationName, new Timestamp(System.currentTimeMillis()));
			userLoggedIn.setLoggedInUiVersion(uiVersion);
			userLoggedIn.setDeamon(deamon);

			UserServiceProxy.getUserLoggedInService().insert(userLoggedIn);
		}

		// 3. Add the user login history
		try
		{
			UserLoggedInHistory userLoggedInHistory = new UserLoggedInHistory();
			userLoggedInHistory.setKey(new UserLoggedInHistoryKey(userLoggedIn.getKey().getUserId(), userLoggedIn.getKey().getUIName(), userLoggedIn.getLoggedInTime()));
			userLoggedInHistory.setWorkStationName(userLoggedIn.getWorkStationName());
			userLoggedInHistory.setLoggedOutTime(null);
			userLoggedInHistory.setLoggedInUiVersion(uiVersion);
			userLoggedInHistory.setDeamon(deamon);
			UserServiceProxy.getUserLoggedInHistoryService().insert(userLoggedInHistory);
		}
		catch (Exception ex)
		{
			log.error(ex);
		}
	}

	public void OICLogOut(String userId, String uiName/*, String workstationName*/) throws FrameworkErrorSignal, NotFoundSignal
	{

		UserLoggedInKey userLoggedInKey = new UserLoggedInKey(userId, uiName);

		// 1. Check if user is logged in
		UserLoggedIn userLoggedIn = null;
		try
		{
			userLoggedIn = UserServiceProxy.getUserLoggedInService().selectByKey(userLoggedInKey);
		} catch (NotFoundSignal e)
		{
			log.warn(e);
		}

//		if(workstationName=="")
//			workstationName = null;
//
//		// 2. Check if workstation is the same as that of logged in
//		if (StringUtils.equalsIgnoreCase(userLoggedIn.getWorkStationName(), workstationName) == false)
//		{
//			throw new FrameworkErrorSignal(ExceptionKey.User_InvalidWorkStation, ObjectUtil.getString(userLoggedInKey),
//					userId, workstationName, userLoggedIn.getWorkStationName());
//		}

		// 3. Remove UserLoggedIn
		UserServiceProxy.getUserLoggedInService().delete(userLoggedInKey);

		// 4. Update the user login history
		try
		{
			UserLoggedInHistory userLoggedInHistory = new UserLoggedInHistory();

			userLoggedInHistory.setKey(new UserLoggedInHistoryKey(userLoggedIn.getKey().getUserId(), userLoggedIn.getKey().getUIName(), userLoggedIn.getLoggedInTime()));
			userLoggedInHistory.setWorkStationName(userLoggedIn.getWorkStationName());
			userLoggedInHistory.setLoggedOutTime(new Timestamp(Calendar.getInstance().getTimeInMillis()));
			userLoggedInHistory.setLoggedInUiVersion(userLoggedIn.getLoggedInUiVersion());

			UserServiceProxy.getUserLoggedInHistoryService().update(userLoggedInHistory);
		}
		catch (Exception ex)
		{
			log.error(ex);
		}
	}

	/*
	* Name : logOut
	* Desc : This function is logOut
	* Author : ZXY Team, Inc
	* Date : 2013.01.03
	*/
	public void logOut(String userId,
					   String uiName,
					   String workStationName)
	throws InvalidStateTransitionSignal, FrameworkErrorSignal, NotFoundSignal, DuplicateNameSignal
	{
		try{
			OICLogOut(userId, uiName);

//			if(uiName.equals("OIC"))
//			{
//				OICLogOut(userId, uiName);
//			}
//			else
//			{
//				UserServiceProxy.getUserInfoService().logOut(userId, uiName, workStationName);
//			}
		}catch(Exception e){
			log.warn(e);
		}
	}

	/*
	* Name : changePassword
	* Desc : This function is changePassword
	* Author : ZXY Team, Inc
	* Date : 2013.01.03
	*/
	public void changePassword(String userId,
							   String oldPassword,
							   String newPassword)
	throws InvalidStateTransitionSignal, FrameworkErrorSignal, NotFoundSignal, DuplicateNameSignal, Exception
	{
		try{
			UserServiceProxy.getUserInfoService().changePassword(userId, oldPassword, newPassword);
		}catch(Exception e){
			throw new CustomException("User-0002", userId, newPassword);
		}
	}

	/*
	* Name : changeGOTPassword
	* Desc : This function is changeGOTPassword
	* Author : ZXY Team, Inc
	* Date : 2017.03.30
	*/
	public void changeGOTPassword(String userId,
							   String oldGOTPassword,
							   String newGOTPassword)
	throws InvalidStateTransitionSignal, FrameworkErrorSignal, NotFoundSignal, DuplicateNameSignal, Exception
	{
		try{
			UserInfoKey userInfoKey = new UserInfoKey();
			userInfoKey.setUserId(userId);

			UserInfo userInfo = UserServiceProxy.getUserInfoService().selectByKey(userInfoKey);

			if(StringUtils.equals(oldGOTPassword, userInfo.getSpecialPassword()) == false) {
				throw new CustomException("User-0002", userId, oldGOTPassword);
			}

			userInfo.setSpecialPassword(newGOTPassword);
			UserServiceProxy.getUserInfoService().update(userInfo);

		}catch(Exception e){
			throw new CustomException("User-0002", userId, oldGOTPassword);
		}
	}

	/*
	* Name : verifyPassword
	* Desc : This function is verifyPassword
	* Author : ZXY Team, Inc
	* Date : 2013.01.03
	*/
	public void verifyPassword(String userId,
							   String password)
	throws InvalidStateTransitionSignal, FrameworkErrorSignal, NotFoundSignal, DuplicateNameSignal, Exception

	{
        if ( !(UserServiceProxy.getUserInfoService().verifyPassword(userId, password)))
        {
        	throw new CustomException("User-0002", userId, password);
        }
	}

	/*
	* Name : removeUserProfile
	* Desc : This function is removeUserProfile
	* Author : ZXY Team, Inc
	* Date : 2013.01.03
	*/
	public void removeUserProfile(String userId){
		UserServiceProxy.getUserInfoService().removeUserInfo(userId);
	}

	/*
	* Name : verifyUser
	* Desc : This function is verifyUser
	* Author : ZXY Team, Inc
	* Date : 2013.01.03
	*/
	public UserInfo verifyUser(String userId) throws Exception
	{
		UserInfoKey userProfileKey = new UserInfoKey();

		userProfileKey.setUserId( userId );

		try
		{
			return UserServiceProxy.getUserInfoService().selectByKey( userProfileKey );
		}
		catch ( Exception e )
		{
			throw new CustomException("User-0001", userId);
		}
	}

	public void verifyUserGroupAccessFactory(UserInfo userInfoData, String loginFactory) throws CustomException
	{
		try
		{
			UserGroupKey userGroupKey = new UserGroupKey(userInfoData.getUserGroupName());
			UserGroup userGroupData = UserServiceProxy.getUserGroupService().selectByKey(userGroupKey);

			String accessFactory = userGroupData.getAccessFactory();

			if (StringUtils.equals(accessFactory, loginFactory))
			{
				return;
			}
			else if (StringUtils.equals(accessFactory, GenericServiceProxy.getConstantMap().Factory_All) ||
					 StringUtils.isEmpty(accessFactory))
			{
				return;
			}
			else if (accessFactory.contains("_"))
			{
				String[] accessFactorys = StringUtils.split(accessFactory, "_");

				for (int i = 0; accessFactorys.length > i; i++)
				{
					if (StringUtils.equals(accessFactorys[i], loginFactory))
					{
						return;
					}
				}
			}

			throw new CustomException("User-0005", userInfoData.getKey().getUserId(), userInfoData.getUserGroupName(), loginFactory);
		}
		catch (NotFoundSignal nfs)
		{
			throw new CustomException("User-0005", userInfoData.getKey().getUserId(), userInfoData.getUserGroupName(), loginFactory);
		}
	}


	/*
	* Name : userValidation
	* Desc : This function is userValidation
	* Author : ZXY Team, Inc
	* Date : 2015.05.11
	*/
	public void userValidation(String userId, String password, String shopName) throws Exception
	{

		UserInfo userInfoData = this.verifyUser(userId);

		this.verifyUserGroupAccessFactory(userInfoData, shopName);

		this.verifyPassword(userId, password);
	}

	/*
	* Name : verifyGOTPassword
	* Desc : This function is userValidation
	* Author : ZXY Team, Inc
	* Date : 2017.06.08
	*/
	public void verifyGOTPassword(String userId, String gotPassword)
			throws Exception, CustomException {
		UserInfo userInfoData = this.verifyUser(userId);

		if (StringUtils.equals(gotPassword, userInfoData.getSpecialPassword()) == false) {
			throw new CustomException("User-0007", userId, gotPassword);
		}
	}
}
