package com.ffii.core.entity;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Optional;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;

import org.springframework.security.core.context.SecurityContextHolder;

/** @author Fung */
@MappedSuperclass
public abstract class BaseEntity<ID extends Serializable> extends IdEntity<ID> {

	/** start from 0 */
	@NotNull
	@Version
	@Column
	private Integer version;

	@NotNull
	@Column(updatable = false)
	private LocalDateTime created;

	@Column(updatable = false)
	private String createdBy;

	@NotNull
	@Column
	private LocalDateTime modified;

	@Column
	private String modifiedBy;

	@NotNull
	@Column
	private Boolean deleted;

	@PrePersist
	public void autoSetCreated() {
		this.setCreated(LocalDateTime.now());
		this.setModified(LocalDateTime.now());
		this.setDeleted(Boolean.FALSE);

		Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
				.ifPresentOrElse(
						authentication -> {
							this.setCreatedBy(authentication.getName());
							this.setModifiedBy(authentication.getName());
						},
						() -> {
							this.setCreatedBy(null);
							this.setModifiedBy(null);
						});
	}

	@PreUpdate
	public void autoSetModified() {
		this.setModified(LocalDateTime.now());
		Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()).ifPresentOrElse(
				authentication -> this.setModifiedBy(authentication.getName()),
				() -> this.setModifiedBy(null));
	}

	// getter and setter

	public Integer getVersion() {
		return this.version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	public LocalDateTime getCreated() {
		return this.created;
	}

	public void setCreated(LocalDateTime created) {
		this.created = created;
	}

	public String getCreatedBy() {
		return this.createdBy;
	}

	public void setCreatedBy(String createdBy) {
		this.createdBy = createdBy;
	}

	public LocalDateTime getModified() {
		return this.modified;
	}

	public void setModified(LocalDateTime modified) {
		this.modified = modified;
	}

	public String getModifiedBy() {
		return this.modifiedBy;
	}

	public void setModifiedBy(String modifiedBy) {
		this.modifiedBy = modifiedBy;
	}

	public Boolean isDeleted() {
		return this.deleted;
	}

	public Boolean getDeleted() {
		return this.deleted;
	}

	public void setDeleted(Boolean deleted) {
		this.deleted = deleted;
	}

}