package info.bukova.isspst.ui.mail;

import info.bukova.isspst.data.Address;
import info.bukova.isspst.data.Member;
import info.bukova.isspst.data.User;
import info.bukova.isspst.mail.MailMessage;
import info.bukova.isspst.mail.Mailer;
import info.bukova.isspst.reporting.Generator;
import info.bukova.isspst.reporting.GeneratorFactory;
import info.bukova.isspst.reporting.ReportDefinition;
import info.bukova.isspst.services.addressbook.AdbService;
import info.bukova.isspst.services.users.UserService;
import info.bukova.isspst.ui.DocumentViewModel;
import org.springframework.security.access.AccessDeniedException;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ExecutionArgParam;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Window;

import java.util.ArrayList;
import java.util.List;

import static ch.lambdaj.Lambda.filter;
import static ch.lambdaj.Lambda.having;
import static ch.lambdaj.Lambda.on;
import static org.hamcrest.Matchers.startsWith;

public class MailForm extends DocumentViewModel
{
	
	@WireVariable
	private Mailer mailer;
	@WireVariable
	private ReportDefinition reportDefinition;
	@WireVariable
	private GeneratorFactory genFactory;
	@WireVariable
	private UserService userService;
	@WireVariable
	private AdbService adbService;
	private MailMessage message;
	private String to;
	private String cc;
	private String bcc;
	private String attachement;
	private boolean report;
	private List<Address> addressbook;
	private List<User> users;
	private List<Address> selectedAddresses;
	private List<User> selectedUsers;
	private int adbType;
	private String findAddress;
	
	@Init(superclass = true)
	public void init(@ExecutionArgParam("report") Boolean report) {
		message = new MailMessage();
		message.setHtml(true);
		this.report = report;
		if (report) {
			attachement = "report.pdf";
		}
		
		try {
			addressbook = adbService.getAll();
		} catch (AccessDeniedException e) {
			addressbook = new ArrayList<Address>();
		}
		
		users = userService.getUsersForCombo();
		
		selectedAddresses = new ArrayList<Address>();
		selectedUsers = new ArrayList<User>();
		
		to = "";
		cc = "";
		bcc = "";
	}
	
	@Command
	public void send(@BindingParam("window") Window window) {
		message.setTo(to.split(";"));
		
		if (cc != null && !cc.isEmpty()) {
			message.setCc(cc.split(";"));
		}
		
		if (bcc != null && !bcc.isEmpty()) {
			message.setCc(bcc.split(";"));
		}
		
		message.setFrom(userService.getCurrent().getEmail());
		
		if (report) {
			Generator generator = genFactory.createGenerator(reportDefinition);
			message.setAttachementData(generator.generate());
			message.setAttachementName("report.pdf");
			message.setContentType("application/pdf");
		}
		
		mailer.send(message);
		window.detach();
	}
	
	@Command
	@NotifyChange("to")
	public void addTo() {
		to = appendAddress(to, selAddrs());
	}
	
	@Command
	@NotifyChange("cc")
	public void addCc() {
		cc = appendAddress(cc, selAddrs());
	}
	
	@Command
	@NotifyChange("bcc")
	public void addBcc() {
		bcc = appendAddress(bcc, selAddrs());
	}
	
	@Command
	@NotifyChange({"selectedAddresses", "selectedUsers"})
	public void find() {
		if (adbType == 0) {
			List<User> found = filter(having(on(Member.class).getFullName(), startsWith(findAddress)), users);
			
			if (!found.isEmpty()) {
				selectedUsers.clear();
				if (!findAddress.isEmpty() && found.get(0).getEmail() != null && !found.get(0).getEmail().isEmpty()) {
					selectedUsers.add(found.get(0));
				}
			}
				
		} else {
			List<Address> found = filter(having(on(Address.class).getCompany(), startsWith(findAddress)), addressbook);
			
			if (!found.isEmpty()) {
				selectedAddresses.clear();
				if (!findAddress.isEmpty() && found.get(0).getEmail() != null && !found.get(0).getEmail().isEmpty()) {
					selectedAddresses.add(found.get(0));
				}
			}
		}
	}
	
	private String appendAddress(String field, List<String> addrs) {
		for (String addr : addrs) {
			if (field.isEmpty()) {
				field = addr;
			} else {
				field += "; " + addr;
			}
		}
		
		return field;
	}
	
	private List<String> selAddrs() {
		List<String> ret = new ArrayList<String>();
		
		if (adbType == 1) {
			for (Address addr : selectedAddresses) {
				ret.add(addr.getCompany() + " <" + addr.getEmail() + ">");
			}
		} else {
			for (User u : selectedUsers) {
				ret.add(u.getFullName() + " <" + u.getEmail() + ">");
			}
		}
		return ret;
	}

	public MailMessage getMessage() {
		return message;
	}

	public void setMessage(MailMessage message) {
		this.message = message;
	}

	public String getTo() {
		return to;
	}

	public void setTo(String to) {
		this.to = to;
	}

	public String getAttachement() {
		return attachement;
	}

	public String getCc() {
		return cc;
	}

	public void setCc(String cc) {
		this.cc = cc;
	}

	public String getBcc() {
		return bcc;
	}

	public void setBcc(String bcc) {
		this.bcc = bcc;
	}

	public List<Address> getAddressbook() {
		return addressbook;
	}

	public List<User> getUsers() {
		return users;
	}

	public int getAdbType() {
		return adbType;
	}

	public void setAdbType(int adbType) {
		this.adbType = adbType;
	}

	public List<Address> getSelectedAddresses() {
		return selectedAddresses;
	}

	public void setSelectedAddresses(List<Address> selectedAddresses) {
		this.selectedAddresses = selectedAddresses;
	}

	public List<User> getSelectedUsers() {
		return selectedUsers;
	}

	public void setSelectedUsers(List<User> selectedUsers) {
		this.selectedUsers = selectedUsers;
	}

	public String getFindAddress() {
		return findAddress;
	}

	public void setFindAddress(String findAddress) {
		this.findAddress = findAddress;
	}

}
