package com.iformall.controller.invest;

import com.alibaba.fastjson.JSON;
import com.iformall.common.ErrorCode;
import com.iformall.common.InvestResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.domain.vo.invest.InvestUserContext;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.service.invest.InvestHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import java.beans.PropertyEditor;
import java.beans.PropertyEditorSupport;
import java.util.function.Function;


@Slf4j
public class InvestBaseController extends BaseController {

	@InitBinder
	public void InitBinder(WebDataBinder dataBinder) {
		super.InitBinder(dataBinder);
		registerEnumEditor(dataBinder, EnumCustomerType.class, "customerType") ;
		registerEnumEditor(dataBinder, EnumCustomerRatingType.class, "customerRatingType") ;
		registerEnumEditor(dataBinder, EnumTaskStatus.class, "taskStatus") ;
		registerEnumEditor(dataBinder, EnumFollowType.class, "type") ;
		registerEnumEditor(dataBinder, EnumRemindDateType.class, "dateType") ;
	}

	public <R, T> InvestResultData<R> execute(T params, Function<T, R> function) {
		try {
			log.debug("[" + getIpAddr() + "] request , params : {}", JSON.toJSONString(params));
			setUserRule();
			InvestUserContext.setUser(getUser());
			R r = function.apply(params);
			return new InvestResultData(r);
		} catch (MallinkException e) {
			log.error("execute error", e);
			return new InvestResultData(e.getErrorCode(), e.getMessage());
		} catch (NullPointerException e) {
			ErrorCode errorCode = ErrorCode.SYS_NULLPOINTER_ERROR ;
			log.error("execute error {}", errorCode.getMessage());
			return new InvestResultData(errorCode);
		} catch (Exception e) {
			log.error("execute error", e);
			return new InvestResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(),e.getMessage());
		} finally {
			InvestUserContext.remove();
		}
	}

	private void setUserRule() {
		EnumInvestUserType investUserType = EnumInvestUserType.getEnum(getUser().getInvestRule()) ;
		InvestUserContext.setInvestUserType(investUserType);
	}

	private <T extends Enum<T>> void registerEnumEditor(WebDataBinder binder, Class<T> clz, String propertyName) {
		binder.registerCustomEditor(clz, propertyName, newEnumEditor(clz));
	}

	private <T extends Enum<T>> PropertyEditor newEnumEditor(Class<T> clz) {
		return new PropertyEditorSupport() {
			@Override
			public void setAsText(String text) {
				try {
					setValue(InvestHelper.codeOf(clz, text));
				} catch (Exception NumberFormatException) {
					setValue(InvestHelper.valueOf(clz, text));
				}
			}
		};
	}
}
