package de.hsadmin.mods.dom;

import static javax.persistence.FetchType.EAGER;
import static javax.persistence.GenerationType.SEQUENCE;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;

import de.hsadmin.core.model.AbstractEntity;
import de.hsadmin.core.model.FieldValidation;
import de.hsadmin.mods.user.UnixUser;

@Entity(name = "Domains")
@Table(name = "domain")
@SequenceGenerator(name = "DomainsSeqGen", sequenceName = "domain_domain_id_seq")
public class Domain extends AbstractEntity {

	private static final long serialVersionUID = -7496110900868795840L;

	@Id
	@Column(name = "domain_id", columnDefinition = "integer")
	@GeneratedValue(strategy = SEQUENCE, generator = "DomainsSeqGen")
	private long id;

	@FieldValidation("[a-z0-9\\-\\.]*")
	@Column(name = "domain_name", columnDefinition = "character varying(256)", nullable = false)
	private String name;

	@JoinColumn(name = "domain_owner", columnDefinition = "integer", nullable = false)
	@ManyToOne(fetch = EAGER)
	private UnixUser user;

	@FieldValidation("[a-z]*")
	@Column(name = "domain_status", columnDefinition = "character varying(12)", nullable = false)
	private String status;

	@Column(name = "domain_status_changed", columnDefinition = "date", nullable = false)
	@Temporal(javax.persistence.TemporalType.DATE)
	private Date statusChanged;

	@Column(name = "domain_filed", columnDefinition = "date")
	@Temporal(javax.persistence.TemporalType.DATE)
	private Date filed;

	@Column(name = "domain_since", columnDefinition = "date")
	@Temporal(javax.persistence.TemporalType.DATE)
	private Date since;

	@Column(name = "domain_until", columnDefinition = "date")
	@Temporal(javax.persistence.TemporalType.DATE)
	private Date until;

	@FieldValidation("[a-z0-9\\-\\.]*")
	@Column(name = "domain_dns_master", columnDefinition = "character varying(64)")
	private String dnsMaster;

	public Domain() {
	}

	public Domain(String name, UnixUser user) {
		this.name = name;
		this.user = user;
		this.statusChanged = new java.util.Date();
		this.status = Status.FILED.toString();
	}

	public static String createQueryFromStringKey(String humanKey) {
		return "obj.name='" + humanKey + "'";
	}

	@Override
	public String createStringKey() {
		return getName();
	}

	@Override
	public long id() {
		return id;
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public UnixUser getUser() {
		return user;
	}

	public void setUser(UnixUser user) {
		this.user = user;
	}

	public Status getStatus() {
		return Status.valueFor(status);
	}

	public void setStatus(Status status) {
		this.status = status.toString();
	}

	public Date getStatusChanged() {
		return statusChanged;
	}

	public void setStatusChanged(Date statusChanged) {
		this.statusChanged = statusChanged;
	}

	public Date getFiled() {
		return filed;
	}

	public void setFiled(Date filed) {
		this.filed = filed;
	}

	public Date getSince() {
		return since;
	}

	public void setSince(Date since) {
		this.since = since;
	}

	public Date getUntil() {
		return until;
	}

	public void setUntil(Date until) {
		this.until = until;
	}

	public String getDnsMaster() {
		return dnsMaster;
	}

	public void setDnsMaster(String dnsMaster) {
		this.dnsMaster = dnsMaster;
	}

	@Override
	public boolean isNew() {
		return id == 0;
	}

	public boolean isReadAllowedFor(UnixUser loginUser) {
		return loginUser.hasHostmasterRole() || // hostmaster
				user.getId() == loginUser.getId() || // dom-admin
				user.getPac().getName().equals(loginUser.getName()) || // pac-admin
				user.getPac().getCustomer().getName().equals(loginUser.getName()); // customer
	}

	public boolean isWriteAllowedFor(UnixUser loginUser) {
		return isReadAllowedFor(loginUser);
	}

	@Override
	public String getHiveName() {
		if (isNew())
			return null;
		else
			return getUser().getHiveName();
	}

	@Override
	public UnixUser owningUser(EntityManager em) {
		return user;
	}

	public static String restriction() {
		return
			// all doms of all pacs of customer
			"obj.user.pac.customer.name=:loginUserName OR " +
			// all doms of packet admin
			"obj.user.pac.name=:loginUserName OR " +
			// all domains of the user itself
			"obj.user=:loginUser";
	}

	public static enum Status {
		NONE(""), 
		ERROR("error"), 
		FILED("filed"), 
		SELF("self"), 
		REGISTERING("registering"), 
		REGISTERED("registered"), 
		TRANSFERRING("transferring"), 
		NACK_RECEIVED("KK-NACK"), 
		ACK_RECEIVED("KK-ACK"), 
		MANAGED("connected"), 
		LEAVE_SIGNALLED("KK-sig"), 
		LEAVING("leaving"), 
		GONE("gone"), 
		CLOSE_REQUESTED("CLO-req"), 
		CLOSING("closing"), 
		CLOSED("closed");
	
		private Status(String aValue) {
			this.aValue = aValue;
		}
	
		public String toString() {
			return aValue;
		}
	
		private String aValue;
	
		public static Status valueFor(String str) {
			for (Status val : Status.values())
				if (val.toString().equals(str))
					return val;
			return null;
		}
	}

}
