package com.crunii.micro.core.distributed;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.crunii.micro.common.constants.CommonConstants;
import org.hibernate.HibernateException;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;

import javax.persistence.Id;
import java.io.Serializable;
import java.lang.reflect.Field;

/**
 * 主键生成策略 实体中的ID 为long或者String类型都可以生成
 * 
 * @author 谌红霜
 *
 */
public class DistributedSnowFlakeId implements IdentifierGenerator {

	public final static String PREFIX = "prefix";

	public final static String AUTOID = "autoId";

	private static Snowflake snowflake = IdUtil.getSnowflake(1, 1);

	public static void changeSnowflakeWorkerId(int workerId){
		snowflake = IdUtil.getSnowflake(workerId);
	}

	@Override
	public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
		Class<? extends Object> clazz = object.getClass();
		GenericGenerator annotation = clazz.getAnnotation(GenericGenerator.class);
		Parameter[] parameters = annotation.parameters();
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			Id idAnno = field.getAnnotation(Id.class);
			if (null != idAnno) {
				Class<?> type = field.getType();
				if (type.equals(String.class)) {
					String prefix = "";
					for (int i = 0; i < parameters.length; i++) {
						Parameter parameter = parameters[i];
						String name = parameter.name();
						String value = parameter.value();
						if (PREFIX.equals(name)) {
							prefix = value;
						}
					}
					return prefix + snowflake.nextId();
				} else if (type.equals(Long.class)) {
					field.setAccessible(true);
					for (int i = 0; i < parameters.length; i++) {
						Parameter parameter = parameters[i];
						String name = parameter.name();
						String value = parameter.value();
						if (AUTOID.equalsIgnoreCase(name) && value.equals(CommonConstants.TURN_OFF_AUTO_ID)) {
							try {
								if (field.get(object) == null) {
									return snowflake.nextId();
								} else {
									return (long) field.get(object);
								}
							} catch (IllegalArgumentException | IllegalAccessException e) {
								e.printStackTrace();
							}
						}
					}
				}
			}
		}
		return snowflake.nextId();
	}

}
