package com.uas.platform.b2b.support;

import com.uas.platform.b2b.model.Enterprise;
import com.uas.platform.b2b.model.Role;
import com.uas.platform.b2b.model.SigninLog;
import com.uas.platform.b2b.model.User;
import com.uas.platform.b2b.service.SigninLogService;
import com.uas.platform.b2b.service.UserService;
import com.uas.platform.core.model.Constant;
import com.uas.platform.core.util.AgentUtils;
import com.uas.platform.core.util.serializer.FlexJsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceResolver;
import org.springframework.mobile.device.LiteDeviceResolver;
import org.springframework.mobile.device.site.SitePreference;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

/**
 * @date 2016年8月31日上午10:55:13
 *       <p>
 *       切换到单点登录
 *       </p>
 * @author yingp
 *
 */
@Deprecated
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

	@Autowired
	private UserService userService;

	@Autowired
	private SigninLogService signinLogService;

	private final static String paramEN = "t_enuu";

	private RequestCache requestCache = new HttpSessionRequestCache();

	private final DeviceResolver deviceResolver;

	public CustomAuthenticationSuccessHandler() {
		this(new LiteDeviceResolver());
	}

	public CustomAuthenticationSuccessHandler(DeviceResolver deviceResolver) {
		this.deviceResolver = deviceResolver;
	}

	@Override
	public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response,
			final Authentication authentication) throws ServletException, IOException {
		User user = userService.findUserByUserUU(Long.parseLong(authentication.getName()));
		if (CollectionUtils.isEmpty(user.getEnterprises())) {
			response.setStatus(HttpStatus.BAD_REQUEST.value());
			response.addHeader("Content-Type", "application/text; charset=utf-8");
			PrintWriter printWriter = response.getWriter();
			printWriter.append("您的账号未绑定企业或已被删除！");
			printWriter.flush();
			printWriter.close();
			return;
		}
		// Device device = this.deviceResolver.resolveDevice(request);
		if (user.getEnterprises().size() > 1) {// need to choose enterprise
			if (!chooseEnterprise(request, response, user)) {
				response.setStatus(HttpStatus.MULTI_STATUS.value());
				response.addHeader("Content-Type", "application/json; charset=utf-8");
				PrintWriter printWriter = response.getWriter();
				printWriter.append(FlexJsonUtils.toJsonArray(getEnterprises(user)));
				printWriter.flush();
				printWriter.close();
				return;
			}
		} else {
			user.setCurrentEnterprise();
		}

		logSession(request, user);

		final SavedRequest savedRequest = requestCache.getRequest(request, response);

		if (savedRequest == null) {
			clearAuthenticationAttributes(request);
			return;
		}
		final String targetUrlParameter = getTargetUrlParameter();
		if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
			requestCache.removeRequest(request, response);
			clearAuthenticationAttributes(request);
			return;
		}

		clearAuthenticationAttributes(request);
		PrintWriter printWriter = response.getWriter();
		printWriter.append(savedRequest.getRedirectUrl());
		printWriter.flush();
		printWriter.close();
	}

	public void setRequestCache(final RequestCache requestCache) {
		this.requestCache = requestCache;
	}

	/**
	 * 登录认证成功后，user写到session
	 * 
	 * @param request
	 * @param authentication
	 */
	private void logSession(HttpServletRequest request, User user) {
		Set<Role> roles = user.getRoles();
		if (!CollectionUtils.isEmpty(roles)) {
			for (Role role : roles) {
				if (role.isSys()) {// 超级账号
					user.setIssys(Constant.YES);
					break;
				}
			}
		}
		user.setIp(AgentUtils.getIp(request));
		request.getSession().setAttribute("user", user);
		// 记录登录日志
		SitePreference preference = getDefaultSitePreferenceForDevice(this.deviceResolver.resolveDevice(request));
		signinLogService.save(new SigninLog(user, preference, false));

	}

	private SitePreference getDefaultSitePreferenceForDevice(Device device) {
		if (device == null) {
			return null;
		}
		if (device.isMobile()) {
			return SitePreference.MOBILE;
		}
		if (device.isTablet()) {
			return SitePreference.TABLET;
		}
		return SitePreference.NORMAL;
	}

	private boolean chooseEnterprise(final HttpServletRequest request, final HttpServletResponse response, User user) throws IOException {
		String enUU = request.getParameter(paramEN);
		boolean choosed = false;
		if (enUU != null) {
			for (Enterprise enterprise : user.getEnterprises()) {
				if (enterprise.getUu().toString().equals(enUU)) {
					user.setEnterprise(enterprise);
					choosed = true;
					break;
				}
			}
		}
		return choosed;
	}

	private List<Map<String, Object>> getEnterprises(User user) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		SigninLog log = signinLogService.findLast(user.getUserUU());
		Long lastEn = null;
		if (log != null) {
            lastEn = log.getEnUU();// 可以优先选中最近一次登录的企业
        }
		for (Enterprise enterprise : user.getEnterprises()) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("enName", enterprise.getEnName());
			map.put("uu", enterprise.getUu());
			if (lastEn != null && enterprise.getUu().equals(lastEn)) {
                map.put("isLast", true);
            }
			list.add(map);
		}
		return list;
	}

}
