package info.bukova.isspst.ui.main.orders.requirements;

import info.bukova.isspst.data.MUnitEmb;
import info.bukova.isspst.data.Material;
import info.bukova.isspst.data.Requirement;
import info.bukova.isspst.data.RequirementItem;
import info.bukova.isspst.data.RequirementSubject;
import info.bukova.isspst.data.Workgroup;
import info.bukova.isspst.services.requirement.RequirementService;
import info.bukova.isspst.services.requirement.RequirementTypeService;
import info.bukova.isspst.services.users.UserService;
import info.bukova.isspst.services.workgroups.WorkgroupService;
import info.bukova.isspst.ui.FormViewModel;
import info.bukova.isspst.validators.RequirementFormValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.bind.BindUtils;
import org.zkoss.bind.SimpleForm;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.GlobalCommand;
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 org.zkoss.zul.impl.InputElement;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class RequirementForm extends FormViewModel<Requirement>
{
	private final static Logger log = LoggerFactory.getLogger(RequirementForm.class.getName());

	@WireVariable
	private UserService userService;

	@WireVariable
	private WorkgroupService workgroupService;

	@WireVariable
	private RequirementTypeService reqTypeService;

	@WireVariable
	private RequirementService requirementService;

	/**
	 * Seznam obsahující kód a název skupiny materálu/služby
	 */
	private List<RequirementSubject> requirementGroups;

	public List<RequirementSubject> getRequirementGroups()
	{
		return requirementGroups;
	}

	public void setRequirementGroups(List<RequirementSubject> requirementGroups)
	{
		this.requirementGroups = requirementGroups;
	}

	private RequirementItem selectedItem;

	private int selItemIndex;

	private RequirementFormValidator requirementFormValidator;

	private List<RequirementItem> syncItems;

	private List<Workgroup> centres;

	public List<Workgroup> getCentres()
	{
		return centres;
	}

	public RequirementItem getSelectedItem()
	{
		return selectedItem;
	}

	public void setSelectedItem(RequirementItem selectedItem)
	{
		this.selectedItem = selectedItem;
	}

	public int getSelItemIndex()
	{
		return selItemIndex;
	}

	public void setSelItemIndex(int selItemIndex)
	{
		this.selItemIndex = selItemIndex;
	}

	public RequirementFormValidator getRequirementFormValidator()
	{
		return requirementFormValidator;
	}

	public void setRequirementFormValidator(RequirementFormValidator requirementFormValidator)
	{
		this.requirementFormValidator = requirementFormValidator;
	}

	@Init(superclass = true)
	public void initRequirementForm()
	{
		this.setSelItemIndex(-1);
		this.setRequirementFormValidator(new RequirementFormValidator());
		this.setSyncItems(this.getDataBean().getItems());
		requirementService.loadType(getDataBean());

		if (isEditRec()) {
			List<Workgroup> current = new ArrayList<Workgroup>();
			current.add(getDataBean().getCentre());
			this.centres = current;
		} else {
			this.centres = reqTypeService.filterCentres(getDataBean().getType(), workgroupService.getUserCentres(userService.getCurrent(), true));
		}
	}

	public List<RequirementItem> getSyncItems()
	{
		return syncItems;
	}

	public void setSyncItems(List<RequirementItem> syncItems)
	{
		this.syncItems = syncItems;
	}

	@Command
	@NotifyChange({ "selItemIndex", "selectedItem" })
	public void onFocusItem(@BindingParam("item") RequirementItem item, @BindingParam("ctrl") InputElement ctrl)
	{
		this.selItemIndex = this.getDataBean().getItems().indexOf(item);
		this.selectedItem = item;

		if (ctrl != null)
		{
			ctrl.select();
		}
	}

	protected void calcAndUpdateFormTotalPrice(SimpleForm form)
	{
		if (form != null)
		{
			BigDecimal sumTotal = requirementService.calcSumTotalFromItems(this.getDataBean().getItems());
			form.setField("sumTotal", sumTotal);
			BindUtils.postNotifyChange(null, null, form, "*");
		}
	}

	@Command
	@NotifyChange({ "syncItems", "selItemIndex", "selectedItem" })
	public void removeItem(@BindingParam("form") SimpleForm form, @BindingParam("item") RequirementItem item)
	{
		if (item != null)
		{
			this.getDataBean().getItems().remove(item);
			this.selItemIndex = -1;
			this.selectedItem = null;
			this.calcAndUpdateFormTotalPrice(form);
		}
	}

	@GlobalCommand("insertSelectedItem")
	@NotifyChange({ "syncItems", "selItemIndex", "selectedItem" })
	public void insertSelectedItem(@BindingParam("selected") RequirementSubject selected, @BindingParam("window") Window window)
	{
		if (selected != null)
		{
			RequirementItem item = new RequirementItem();
			boolean isMaterial = (selected instanceof Material);
			// boolean isServiceItem = (selected instanceof ServiceItem);

			item.setReqSubject(selected);

			item.setCode(selected.getCode());
			item.setName(selected.getName());
			item.setQuantity(BigDecimal.valueOf(1));
			item.setUnitPrice(BigDecimal.valueOf(0));
			item.setTotal(BigDecimal.valueOf(0));
			item.setDescription(selected.getDescription());

			if (isMaterial)
			{
				Material materialItem = (Material) selected;
				MUnitEmb unit = materialItem.getMunit();

				// if (unit == null)
				// {
				// unit = new MUnitEmb();
				// }

				item.setMunit(unit);
			}

			this.setSelectedItem(item);
			this.getDataBean().addItem(item);
			this.setSelItemIndex(this.getDataBean().getItems().indexOf(item));
		}

		if (window != null)
		{
			window.detach();
		}
	}

	@Command
	@NotifyChange({ "selectedItem" })
	public void recalculate(@BindingParam("form") SimpleForm form, @BindingParam("changed") String source)
	{
		if (this.selectedItem == null)
		{
			log.warn("Zavolat z formuláře onFocus pro nastavení vybrané položky!");
			return;
		}

		// Recalculate selected item
		if ((source != null) && (source.equals("total")))
		{
			this.selectedItem = requirementService.calcItemValuesFromItemTotal(this.selectedItem);
		}
		else
		{
			this.selectedItem = requirementService.calcTotalInItem(this.selectedItem);
		}

		// Calculate total price at form
		this.calcAndUpdateFormTotalPrice(form);
	}

	@Command
	@NotifyChange({ "selectedItem" })
	public void onChangeGroup()
	{
		// Někdo změnil skupinu materiálu nebo služby
		if (this.selectedItem == null)
		{
			log.warn("Zavolat z formuláře onFocus pro nastavení vybrané položky!");
			return;
		}

		// Zjistit, zda je propojená skupina materiálu nebo služeb
		RequirementSubject subject = this.selectedItem.getReqSubject();

		if (subject != null)
		{
			boolean isMaterial = (subject instanceof Material);

			if (isMaterial)
			{
				Material materialItem = (Material) subject;
				MUnitEmb munit = materialItem.getMunit();
				this.selectedItem.setMunit(munit);
			}

			// Skupina materiálu nebo služeb je propojená, nastavit k zadanému
			// kódu i správný název skupiny materiálu nebo služby
			this.selectedItem.setName(subject.getName());
		}
	}

	@Command
	@NotifyChange({ "syncItems", "selectedItem", "selItemIndex" })
	public void addNewItem()
	{
		RequirementItem item = new RequirementItem();

		item.setReqSubject(null);

		item.setCode("");
		item.setName("");
		item.setQuantity(BigDecimal.valueOf(1));
		item.setUnitPrice(BigDecimal.valueOf(0));
		item.setTotal(BigDecimal.valueOf(0));
		item.setDescription("");
		item.setMunit(new MUnitEmb());

		this.getDataBean().addItem(item);

		this.selItemIndex = this.getDataBean().getItems().indexOf(item);
		this.selectedItem = item;
	}
}
