package eu.dnetlib.goldoa.domain;

import com.google.gwt.user.client.rpc.IsSerializable;

import javax.persistence.*;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * The persistent class for the request database table.
 * 
 */
@Entity
@NamedQuery(name="Request.findAll", query="SELECT r FROM Request r")
public class Request implements IsSerializable {
	private static final long serialVersionUID = 1L;

	public enum RequestStatus implements IsSerializable {

		INCOMPLETE("Incomplete", 0),
		SUBMITTED("Submitted", 1),
		CONDITIONALLY_APPROVED("Conditionally approved", 2),
		APPROVED("Approved", 4),
		REJECTED("Rejected", 8),
		ACCOUNTING_PROCESSING("Processing payment", 16),
		ACCOUNTING_PAID("Paid", 32),
		ACCOUNTING_ON_HOLD("On hold", 64),
		ACCOUNTING_DENIED("Denied", 128),
		COMPLETED("Completed", 256),

		LIBRARY_FUND_SUBMITTED("Submitted (Library block grant)", 512),
		PUBLISHER_FUND_SUBMITTED("Submitted (Publihser block grant)", 1024),

		LIBRARY_FUND_PAID("Paid (Library block grant)", 2048),
		PUBLISHER_FUND_PAID("Paid (Publihser block grant)", 4096);

		private String value;
		private int code;

		RequestStatus(String value, int code) {
			this.value = value;
			this.code = code;
		}

		public String getValue() {
			return value;
		}

		public int getCode() {
			return code;
		}

		public static RequestStatus forStatus(int status) {
			if (status == 0)
				return INCOMPLETE;
			else
				return RequestStatus.values()[((int) Math.round(Math.log(status)/Math.log(2)) + 1)];
		}

	}

	@Id
	@Column(columnDefinition = "text")
	private String id;
	private Float apc;
	private Float apcPaid;
	private Timestamp approvaldate;
	private Timestamp date;
	private Timestamp datePaid;
	private Float discount;
	private Float fundingrequested;
	private Float otherCost;
	private Float projectparticipation;
	private Timestamp submissiondate = new Timestamp(new Date().getTime());
	private Float transferCost;


	@Column(name="publisher_email",columnDefinition = "text")
	private String publisherEmail;

	@Transient
	private Eligibility eligibility;

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "bankAccount")
	private BankAccount bankAccount;

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "bankTransferReceipt")
	private BankTransferReceipt bankTransferReceipt;

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "budget")
	private Budget budget;

	@Basic
	@Convert( converter=CurrencyConverter.class )
	private Currency currency = Currency.EUR;

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "invoice")
	private Invoice invoice;

	@OneToOne
	@JoinColumn(name = "journal")
	private Journal journal;
	
	@OneToOne
	@JoinColumn(name = "organization")
	private Organization organization;

	@OneToOne
	@JoinColumn(name = "project")
	private Project project;

	@OneToOne
	@JoinColumn(name = "publication")
	private Publication publication;

	@OneToOne
	@JoinColumn(name = "publisher")
	private Publisher publisher;

	@OneToOne
	@JoinColumn(name = "researcher")
	private User researcher;

	@Basic
	@Convert( converter=RequestStatusConverter.class )
	private RequestStatus status = RequestStatus.INCOMPLETE;

	@OneToOne
	@JoinColumn(name = "\"user\"")
	private User user;

	@OneToMany(mappedBy = "pk.request",cascade = CascadeType.ALL)
	private List<RequestCoFunder> requestCoFunders = new ArrayList<>();

	@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@JoinTable(name = "request_comment",  joinColumns = {
			@JoinColumn(name = "request", nullable = false, updatable = false)},
			inverseJoinColumns = { @JoinColumn(name = "comment",
					nullable = false, updatable = false) })
	private List<Comment> requestComments = new ArrayList<>();

	public Request() {}

	public String getId() {
		return id;
	}

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

	public Float getApc() {
		return apc;
	}

	public void setApc(Float apc) {
		this.apc = apc;
	}

	public Float getApcPaid() {
		return apcPaid;
	}

	public void setApcPaid(Float apcPaid) {
		this.apcPaid = apcPaid;
	}

	public Timestamp getApprovaldate() {
		return approvaldate;
	}

	public void setApprovaldate(Timestamp approvaldate) {
		this.approvaldate = approvaldate;
	}

	public Timestamp getDate() {
		return date;
	}

	public void setDate(Timestamp date) {
		this.date = date;
	}

	public Timestamp getDatePaid() {
		return datePaid;
	}

	public void setDatePaid(Timestamp datePaid) {
		this.datePaid = datePaid;
	}

	public Float getDiscount() {
		return discount;
	}

	public void setDiscount(Float discount) {
		this.discount = discount;
	}

	public Float getFundingrequested() {
		return fundingrequested;
	}

	public void setFundingrequested(Float fundingrequested) {
		this.fundingrequested = fundingrequested;
	}

	public Float getOtherCost() {
		return otherCost;
	}

	public void setOtherCost(Float otherCost) {
		this.otherCost = otherCost;
	}

	public Float getProjectparticipation() {
		return projectparticipation;
	}

	public void setProjectparticipation(Float projectparticipation) {
		this.projectparticipation = projectparticipation;
	}

	public Timestamp getSubmissiondate() {
		return submissiondate;
	}

	public void setSubmissiondate(Timestamp submissiondate) {
		this.submissiondate = submissiondate;
	}

	public Float getTransferCost() {
		return transferCost;
	}

	public void setTransferCost(Float transferCost) {
		this.transferCost = transferCost;
	}

	public BankAccount getBankAccount() {
		return bankAccount;
	}

	public void setBankAccount(BankAccount bankAccount) {
		this.bankAccount = bankAccount;
	}

	public BankTransferReceipt getBankTransferReceipt() {
		return bankTransferReceipt;
	}

	public void setBankTransferReceipt(BankTransferReceipt bankTransferReceipt) {
		this.bankTransferReceipt = bankTransferReceipt;
	}

	public Budget getBudget() {
		return budget;
	}

	public void setBudget(Budget budget) {
		this.budget = budget;
	}

	public Currency getCurrency() {
		return currency;
	}

	public void setCurrency(Currency currency) {
		this.currency = currency;
	}

	public Invoice getInvoice() {
		return invoice;
	}

	public void setInvoice(Invoice invoice) {
		this.invoice = invoice;
	}

	public Journal getJournal() {
		return journal;
	}

	public void setJournal(Journal journal) {
		this.journal = journal;
	}

	public Organization getOrganization() {
		return organization;
	}

	public void setOrganization(Organization organization) {
		this.organization = organization;
	}

	public Project getProject() {
		return project;
	}

	public void setProject(Project project) {
		this.project = project;
	}

	public Publication getPublication() {
		return publication;
	}

	public void setPublication(Publication publication) {
		this.publication = publication;
	}

	public Publisher getPublisher() {
		return publisher;
	}

	public void setPublisher(Publisher publisher) {
		this.publisher = publisher;
	}

	public User getResearcher() {
		return researcher;
	}

	public void setResearcher(User researcher) {
		this.researcher = researcher;
	}

	public RequestStatus getStatus() {
		return status;
	}

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

	public User getUser() {
		return user;
	}

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

	public List<RequestCoFunder> getRequestCoFunders() {
		return requestCoFunders;
	}

	public void setRequestCoFunders(List<RequestCoFunder> requestCoFunders) {
		this.requestCoFunders = requestCoFunders;
	}

	public List<Comment> getRequestComments() {
		return requestComments;
	}

	public void setRequestComments(List<Comment> requestComments) {
		this.requestComments = requestComments;
	}

	public Eligibility getEligibility() {
		return eligibility;
	}

	public void setEligibility(Eligibility eligibility) {
		this.eligibility = eligibility;
	}

	public String getPublisherEmail() {
		return publisherEmail;
	}

	public void setPublisherEmail(String publisherEmail) {
		this.publisherEmail = publisherEmail;
	}


}