package org.bench4q.master.domain.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.log4j.Logger;
import org.bench4q.share.enums.master.AgentStatus;

@Entity
@Table(name = "agent")
public class Agent {
	private int id;
	protected String hostName;
	protected int port;
	protected int maxLoad;
	protected int remainLoad;
	private AgentStatus currentEnumStatus;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id", nullable = false)
	public int getId() {
		return id;
	}

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

	@Column(name = "hostName", nullable = false)
	public String getHostName() {
		return hostName;
	}

	public void setHostName(String hostName) {
		this.hostName = hostName;
	}

	@Column(name = "port", nullable = false)
	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	@Column(name = "maxLoad", nullable = false)
	public int getMaxLoad() {
		return maxLoad;
	}

	public void setMaxLoad(int maxLoad) {
		this.maxLoad = maxLoad;
	}

	@Column(name = "remainLoad", nullable = false)
	public int getRemainLoad() {
		return remainLoad;
	}

	public void setRemainLoad(int remainLoad) {
		this.remainLoad = remainLoad;
	}

	@Enumerated(EnumType.ORDINAL)
	@Column(name = "currentEnumStatus", nullable = false)
	public AgentStatus getCurrentEnumStatus() {
		return currentEnumStatus;
	}

	public void setCurrentEnumStatus(AgentStatus currentEnumStatus) {
		this.currentEnumStatus = currentEnumStatus;
	}

	public static Agent createAgentWithoutId(Agent agentWithoutInitial) {
		if (agentWithoutInitial.getMaxLoad() > 0) {
			return createAgentWithoutId(agentWithoutInitial.getHostName(),
					agentWithoutInitial.getPort(),
					agentWithoutInitial.getMaxLoad());
		} else {
			return createAgentWithoutId(agentWithoutInitial.getHostName(),
					agentWithoutInitial.getPort(), 500);
		}
	}

	public static Agent createAgentWithoutId(String hostName, int port,
			int maxLoad) {
		Agent agent = new Agent();
		agent.setHostName(hostName);
		agent.setPort(port);
		agent.setMaxLoad(maxLoad);
		agent.setRemainLoad(maxLoad);
		agent.setCurrentEnumStatus(AgentStatus.InIdle);
		return agent;
	}

	public void updateStatus(AgentStatus target) {
		this.setCurrentEnumStatus(target);
	}

	public void resetLoad() {
		this.setRemainLoad(this.getMaxLoad());
	}

	public boolean backLoad(int load) {
		if (!isValidLoadUnderOperate(load)) {
			return false;
		}
		if (load + this.getRemainLoad() > this.getMaxLoad()) {
			Logger.getLogger(Agent.class).error(
					"want to back load which is more than missing");
			return false;
		}
		this.setRemainLoad(this.getRemainLoad() + load);
		if (this.getRemainLoad() == this.getMaxLoad()) {
			this.setCurrentEnumStatus(AgentStatus.InIdle);
		}
		return true;
	}

	@Transient
	private boolean isValidLoadUnderOperate(int requireLoad) {
		if (requireLoad < 0) {
			Logger.getLogger(Agent.class).error(
					"Want to operate a negative load value");
			return false;
		}
		return true;
	}

	public boolean bookTest(int requireLoad) {
		if (!isValidLoadUnderOperate(requireLoad)) {
			return false;
		}
		if (requireLoad > this.getRemainLoad()) {
			Logger.getLogger(Agent.class).error(
					"Want to book test whose load is GT remainLoad");
			return false;
		}
		this.setCurrentEnumStatus(AgentStatus.InRunning);
		this.setRemainLoad(this.getRemainLoad() - requireLoad);
		return true;
	}

	@Transient
	public boolean isInUse() {
		return this.getRemainLoad() < this.getMaxLoad()
				&& this.getCurrentEnumStatus() == AgentStatus.InIdle;
	}

	@Transient
	public boolean isBreakDown() {
		return this.getCurrentEnumStatus() == AgentStatus.BreakDown;
	}
}
