package com.eactive.eai.rms.data.config;

import java.lang.annotation.Annotation;
import java.util.function.Consumer;

import javax.persistence.EntityManagerFactory;
import javax.persistence.metamodel.EntityType;

import org.hibernate.annotations.Table;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class EntityTablePrinter implements ApplicationListener<ContextRefreshedEvent> {

	private EntityManagerFactory entityManagerFactory;

	@Autowired
	public EntityTablePrinter(EntityManagerFactory entityManagerFactory) {
		this.entityManagerFactory = entityManagerFactory;
	}

	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		if (log.isDebugEnabled() && event.getApplicationContext().getParent() == null) {
			log.debug("################### TABLE INFO ###################");
			entityManagerFactory.getMetamodel().getEntities().parallelStream().forEach(this::printEntityTableInfo);
		}
	}

	private void printEntityTableInfo(EntityType<?> entityType) {
		String entityName = entityType.getName();

		// Hibernate Table 정보 출력
		printTableInfo(entityType, Table.class,
				table -> log.debug("Table Name : {} = {} ({})", table.appliesTo(), entityName, table.comment()));

		// JPA Table 정보 출력
		printTableInfo(entityType, javax.persistence.Table.class,
				table -> log.debug("Table Name : {} = {}", table.name(), entityName));
	}

	private <T extends Annotation> void printTableInfo(EntityType<?> entityType, Class<T> annotationClass,
			Consumer<T> printer) {
		T tableAnnotation = entityType.getBindableJavaType().getAnnotation(annotationClass);
		if (tableAnnotation != null) {
			printer.accept(tableAnnotation);
		}
	}

}
