package org.eclipse.osbp.runtime.web.vaadin.components.fields.filter2;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.eclipse.osbp.ecview.core.common.context.ILocaleChangedService;
import org.eclipse.osbp.ecview.core.common.context.IViewContext;
import org.eclipse.osbp.runtime.common.i18n.II18nService;
import org.eclipse.osbp.runtime.web.vaadin.common.data.IBeanSearchServiceFactory;

import com.vaadin.data.Container.Filter;
import com.vaadin.data.util.filter.And;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Grid.Column;

@SuppressWarnings("serial")
public class FilteringComponent<T> extends CustomComponent implements IFilteringComponent, ILocaleChangedService.LocaleListener {

	IViewContext viewContext;

	ComponentContainer mainLayout;
	FormLayout leftForm;
	FormLayout rightForm;
	List<ISingleFilterComponent> components = new ArrayList<>();

	private boolean hideGrid;
	FilteringGridComponent<T> grid;

	private Class<T> rootType;

	private Callback resetFilterCallback;

	private Callback applyFilterCallback;

	private int filterCols;

	private Button search;

	private Button reset;

	private II18nService i18nService;

	public FilteringComponent(IViewContext viewContext, Class<T> rootType, boolean hideGrid) {
		this(viewContext, rootType, 2, hideGrid);
	}

	public FilteringComponent(IViewContext viewContext, Class<T> rootType, int filterCols, boolean hideGrid) {
		this.viewContext = viewContext;
		this.rootType = rootType;
		this.hideGrid = hideGrid;

		if (filterCols < 1 || filterCols > 2) {
			throw new IllegalArgumentException("Columns must be between 1 and 2");
		}
		this.filterCols = filterCols;

		init();
	}

	protected void init() {
		mainLayout = createMainLayout();
		setCompositionRoot(mainLayout);
		setSizeFull();
		ILocaleChangedService service = viewContext.getService(ILocaleChangedService.class.getName());
		service.addLocaleListener(this);

		i18nService = viewContext.getService(II18nService.ID);
		setLocale(viewContext.getLocale());
	}

	protected ComponentContainer createMainLayout() {

		VerticalLayout mainLayout = new VerticalLayout();
		mainLayout.setSizeFull();
		i18nService = viewContext.getService(II18nService.ID);

		// buttons
		//
		search = new Button(Util.getCaption(i18nService, "search", "search", viewContext.getLocale()), e -> {
			applyFilters();
			if (applyFilterCallback != null) {
				applyFilterCallback.callback();
			}
		});
		search.setSizeUndefined();

		reset = new Button(Util.getCaption(i18nService, "reset", "reset", viewContext.getLocale()), e -> {
			resetAllFilters();
			if (resetFilterCallback != null) {
				resetFilterCallback.callback();
			}
		});
		reset.setSizeUndefined();

		HorizontalLayout buttonBar = new HorizontalLayout(search, reset);
		buttonBar.setSizeUndefined();
		mainLayout.addComponent(buttonBar);

		// filter part
		//
		leftForm = new FormLayout();
		leftForm.setSizeFull();
		leftForm.setSpacing(false);
		leftForm.setMargin(false);

		HorizontalLayout filterColsLayout = new HorizontalLayout(leftForm);
		mainLayout.addComponent(filterColsLayout);
		filterColsLayout.setSizeUndefined();
		filterColsLayout.setWidth("100%");
		mainLayout.setComponentAlignment(filterColsLayout, Alignment.TOP_LEFT);

		filterColsLayout.setMargin(new MarginInfo(true, true));
		filterColsLayout.setExpandRatio(leftForm, 1.0f);

		if (filterCols > 1) {
			rightForm = new FormLayout();
			rightForm.setSizeFull();
			rightForm.setSpacing(false);
			rightForm.setMargin(false);
			filterColsLayout.addComponent(rightForm);
		}

		if (rightForm != null) {
			filterColsLayout.setExpandRatio(rightForm, 1.0f);
		}

		if (!hideGrid) {
			// grid part
			grid = new FilteringGridComponent<T>(viewContext);
			grid.init(rootType, viewContext.getService(IBeanSearchServiceFactory.class.getName()));
			grid.setSizeFull();
			mainLayout.addComponent(grid);
			mainLayout.setComponentAlignment(grid, Alignment.TOP_LEFT);
			mainLayout.setExpandRatio(grid, 1.0f);
		}

		return mainLayout;
	}

	/**
	 * Adds a component to the filter component.
	 * 
	 * @param component
	 * @param index
	 */
	public void addComponent(ISingleFilterComponent component, int index) {
		if (filterCols > 1 && index % 2 == 0) {
			rightForm.addComponent(component);
		} else {
			leftForm.addComponent(component);
		}
		component.setSizeFull();

		components.add(component);
	}

	public void removeAllComponents() {
		components.clear();
		leftForm.removeAllComponents();
		if (rightForm != null) {
			rightForm.removeAllComponents();
		}
		if(!hideGrid) {
			grid.removeAllColumns();
		}
	}

	public void setResetFilterCallback(Callback resetFilterCallback) {
		this.resetFilterCallback = resetFilterCallback;
	}

	public void setApplyFilterCallback(Callback applyFilterCallback) {
		this.applyFilterCallback = applyFilterCallback;
	}

	public void setSelectionConsumer(Consumer<T> selectionConsumer) {
		if (grid != null) {
			grid.setSelectionConsumer(selectionConsumer);
		}
	}

	public void addBetweenTextComponent(String propertyId, int index) {
		BetweenTextComponent comp = new BetweenTextComponent(propertyId, viewContext);
		comp.init();
		addComponent(comp, index);
	}

	public <X extends Number & Comparable<?>> void addBetweenDecimalComponent(String propertyId, Class<X> type,
			int index) {
		BetweenDecimalComponent<X> comp = new BetweenDecimalComponent<X>(propertyId, type, viewContext);
		comp.init();
		addComponent(comp, index);
	}

	public void addCompareTextComponent(String propertyId, int index) {
		CompareTextComponent comp = new CompareTextComponent(propertyId, viewContext);
		comp.init();
		addComponent(comp, index);
	}

	public void addCompareDecimalComponent(String propertyId, Class<? extends Number> type, int index) {
		CompareDecimalComponent comp = new CompareDecimalComponent(propertyId, type, viewContext);
		comp.init();
		addComponent(comp, index);
	}

	public void addCompareDateComponent(String propertyId, int index) {
		CompareDateComponent comp = new CompareDateComponent(propertyId, viewContext);
		comp.init();
		addComponent(comp, index);
	}

	public void addBetweenDateComponent(String propertyId, int index) {
		BetweenDateComponent comp = new BetweenDateComponent(propertyId, viewContext);
		comp.init();
		addComponent(comp, index);
	}

	public void addCompareBooleanComponent(String propertyId, int index) {
		CompareBooleanComponent comp = new CompareBooleanComponent(propertyId, viewContext);
		comp.init();
		addComponent(comp, index);
	}

	public void addGridColumn(String propertyId) {
		if(!hideGrid) {
			grid.addColumn(propertyId);
		}
	}

	public void dispose() {
		for (ISingleFilterComponent comp : components) {
			comp.dispose();
		}
		components.clear();

		if(!hideGrid) {
			grid.dispose();
		}
	}

	/**
	 * Returns a proper filter for all components contained.
	 * 
	 * @return
	 */
	public Filter getFilter() {
		List<Filter> filters = components.stream().filter(c -> c.getFilter() != null).map(c -> c.getFilter())
				.collect(Collectors.toList());
		And andFilter = new And(filters.toArray(new Filter[filters.size()]));
		return andFilter;
	}

	@Override
	public void resetAllFilters() {
		for (ISingleFilterComponent comp : components) {
			comp.resetAllFilters();
		}
	}

	@Override
	public void applyFilters() {
		if(!hideGrid) {
			grid.setFilter(getFilter());
		}
	}

	@FunctionalInterface
	interface Callback {
		void callback();
	}

	@Override
	public void localeChanged(Locale locale) {
		search.setCaption(Util.getCaption(i18nService, "search", "search", locale));
		reset.setCaption(Util.getCaption(i18nService, "reset", "reset", locale));
	}

}
