/**
 *                                                                            
 * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 *                                                                            
 * All rights reserved. This program and the accompanying materials           
 * are made available under the terms of the Eclipse Public License v1.0       
 * which accompanies this distribution, and is available at                  
 * http://www.eclipse.org/legal/epl-v10.html                                 
 *                                                                            
 * Contributors:   
 * Florian Pirchner <florian.pirchner@gmail.com> - Initial implementation
 */
package org.eclipse.osbp.vaadin.addons.designer.overlay;

import javax.servlet.annotation.WebServlet;

import org.eclipse.osbp.vaadin.addons.designer.overlay.DesignerOverlayExtension.AddChildEvent;
import org.eclipse.osbp.vaadin.addons.designer.overlay.DesignerOverlayExtension.RemoveChildEvent;
import org.eclipse.osbp.vaadin.addons.designer.overlay.DesignerOverlayExtension.ShowPropertiesEvent;
import org.eclipse.osbp.vaadin.addons.designer.overlay.DesignerOverlayExtension.ShowPropertiesListener;
import org.eclipse.osbp.vaadin.addons.designer.overlay.DesignerOverlayExtension.SwitchEditableEvent;
import org.eclipse.osbp.vaadin.addons.designer.overlay.client.widgets.AlignmentInfo;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.ThemeResource;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Component;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

@SuppressWarnings("serial")
@Theme("valo")
public class OverlayApplication extends UI {

	@WebServlet(value = "/*", asyncSupported = true)
	@VaadinServletConfiguration(productionMode = false, ui = OverlayApplication.class, widgetset = "org.eclipse.osbp.vaadin.addons.designer.overlay.OverlayWidgetset")
	public static class Servlet extends VaadinServlet {
	}

	@Override
	protected void init(VaadinRequest request) {

		TabSheet tabSheet = new TabSheet();
		tabSheet.setSizeFull();
		setContent(tabSheet);

		addGridlayout(tabSheet);
		addHorizontallayout(tabSheet);
		addVerticallayout(tabSheet);
		addLayoutInlayout(tabSheet);
	}

	/**
	 * Add gridlayout to the tabsheet.
	 * 
	 * @param tabSheet
	 */
	private void addGridlayout(TabSheet tabSheet) {
		final GridLayout gridLayout = new GridLayout(3, 3);
		gridLayout.setSizeFull();
		gridLayout.setMargin(true);
		tabSheet.addTab(gridLayout, "GridLayout");

		DesignerOverlayExtension layoutExt = DesignerOverlayExtension.create(gridLayout);
		layoutExt.setSupportsAlignments(false);
		layoutExt.setSupportsMargins(true);
		layoutExt.setSupportsSpacing(true);
		layoutExt.setSupportsPropertiesDialog(true);
		layoutExt.setSupportsRemove(false);
		layoutExt.setSupportsAdd(true);
		layoutExt.setIcon(new ThemeResource("sample/sample.gif"));
		layoutExt.addSwitchEditableListener(new DesignerOverlayExtension.SwitchEditableListener() {
			@Override
			public void switchEditable(DesignerOverlayExtension.SwitchEditableEvent event) {
				gridLayout.setEnabled(!gridLayout.isReadOnly());
			}
		});

		layoutExt.addSwitchMarginListener(new DesignerOverlayExtension.SwitchMarginListener() {
			@Override
			public void switchMargin(DesignerOverlayExtension.SwitchMarginEvent event) {
				gridLayout.setMargin(gridLayout.getMargin().getBitMask() == 0);
			}
		});

		layoutExt.addSwitchSpacingListener(new DesignerOverlayExtension.SwitchSpacingListener() {
			@Override
			public void switchSpacing(DesignerOverlayExtension.SwitchSpacingEvent event) {
				gridLayout.setSpacing(!gridLayout.isSpacing());
			}
		});

		layoutExt.addShowPropertiesListener(new ShowPropertiesListener() {
			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}
		});
		
		layoutExt.addAddChildListener(new DesignerOverlayExtension.AddChildListener() {
			@Override
			public void addChild(DesignerOverlayExtension.AddChildEvent event) {
				gridLayout.addComponent(new TextField("added"));
			}
		});
		
		addToGrid(gridLayout, 0, 0);
		addToGrid(gridLayout, 0, 1);
		addToGrid(gridLayout, 0, 2);
		addToGrid(gridLayout, 1, 0);
		addToGrid(gridLayout, 1, 1);
		addToGrid(gridLayout, 1, 2);
		addToGrid(gridLayout, 2, 0);
		addToGrid(gridLayout, 2, 1);
		addToGrid(gridLayout, 2, 2);
	}

	private void addToGrid(final GridLayout gridLayout, int col, int row) {
		final Component text = new TextField("Text " + col + "/" + row);
		text.setId("Text " + col + "/" + row);
		gridLayout.addComponent(text, col, row);

		DesignerOverlayExtension extension = DesignerOverlayExtension.create(text);
		extension.setSupportsAlignments(true);
		extension.setSupportsMargins(false);
		extension.setSupportsSpacing(false);
		extension.setSupportsPropertiesDialog(true);
		extension.setSupportsRemove(true);
		extension.setSupportsEditable(true);

		extension.addAlignmentChangedListener(new DesignerOverlayExtension.AlignmentChangedListener() {
			@Override
			public void alignmentChanged(DesignerOverlayExtension.AlignmentChangedEvent event) {
				AlignmentInfoUtil.apply(gridLayout, text, event.getAlignment());
			}
		});

		extension.addRemoveChildListener(new DesignerOverlayExtension.RemoveChildListener() {
			@Override
			public void removeChild(RemoveChildEvent event) {
				gridLayout.removeComponent(event.getComponent());
			}
		});

		extension.addSwitchEditableListener(new DesignerOverlayExtension.SwitchEditableListener() {
			@Override
			public void switchEditable(SwitchEditableEvent event) {
				text.setReadOnly(!text.isReadOnly());
			}
		});

		extension.addShowPropertiesListener(new ShowPropertiesListener() {
			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}
		});

		extension.getState().alignment = AlignmentInfo.MIDDLE_CENTER;
		AlignmentInfoUtil.apply(gridLayout, text, AlignmentInfo.MIDDLE_CENTER);
	}

	/**
	 * Add verticallayout to the tabsheet.
	 * 
	 * @param tabSheet
	 */
	private void addVerticallayout(TabSheet tabSheet) {
		final VerticalLayout verticalLayout = new VerticalLayout();
		verticalLayout.setSizeFull();
		verticalLayout.setMargin(true);
		tabSheet.addTab(verticalLayout, "VerticalLayout");

		DesignerOverlayExtension layoutExt = DesignerOverlayExtension.create(verticalLayout);
		layoutExt.setSupportsAlignments(false);
		layoutExt.setSupportsMargins(true);
		layoutExt.setSupportsSpacing(true);
		layoutExt.setSupportsPropertiesDialog(true);
		layoutExt.setSupportsRemove(false);
		layoutExt.setSupportsAdd(true);
		layoutExt.addAllEventHanndler(new DesignerOverlayExtension.AllEventHanndler() {
			@Override
			public void switchEditable(DesignerOverlayExtension.SwitchEditableEvent event) {
				verticalLayout.setReadOnly(!verticalLayout.isReadOnly());
			}

			@Override
			public void switchMargin(DesignerOverlayExtension.SwitchMarginEvent event) {
				verticalLayout.setMargin(verticalLayout.getMargin().getBitMask() == 0);
			}

			@Override
			public void switchSpacing(DesignerOverlayExtension.SwitchSpacingEvent event) {
				verticalLayout.setSpacing(!verticalLayout.isSpacing());
			}

			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}
			
			@Override
			public void addChild(AddChildEvent event) {
				addToVerticalLayout(verticalLayout, 10);
			}
		});

		addToVerticalLayout(verticalLayout, 0);
		addToVerticalLayout(verticalLayout, 1);
		addToVerticalLayout(verticalLayout, 2);
		addToVerticalLayout(verticalLayout, 3);
		addToVerticalLayout(verticalLayout, 4);
		addToVerticalLayout(verticalLayout, 5);
	}

	private void addToVerticalLayout(final VerticalLayout verticalLayout, int index) {
		final TextField text = new TextField("Mouse over " + index);
		text.setId("Mouse over " + index);
		verticalLayout.addComponent(text);

		DesignerOverlayExtension extension = DesignerOverlayExtension.create(text);
		extension.setSupportsAlignments(true);
		extension.setSupportsMargins(false);
		extension.setSupportsSpacing(false);
		extension.setSupportsPropertiesDialog(true);
		extension.setSupportsRemove(true);
		extension.setSupportsEditable(true);

		extension.addAllEventHanndler(new DesignerOverlayExtension.AllEventHanndler() {
			@Override
			public void alignmentChanged(DesignerOverlayExtension.AlignmentChangedEvent event) {
				AlignmentInfoUtil.apply(verticalLayout, text, event.getAlignment());
			}

			@Override
			public void removeChild(RemoveChildEvent event) {
				verticalLayout.removeComponent(event.getComponent());
			}

			@Override
			public void switchEditable(SwitchEditableEvent event) {
				text.setReadOnly(!text.isReadOnly());
			}

			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}
		});

		extension.getState().alignment = AlignmentInfo.TOP_CENTER;
		AlignmentInfoUtil.apply(verticalLayout, text, AlignmentInfo.TOP_CENTER);
	}

	/**
	 * Add horizontallayout to the tabsheet.
	 * 
	 * @param tabSheet
	 */
	private void addHorizontallayout(TabSheet tabSheet) {
		final HorizontalLayout horizontalLayout = new HorizontalLayout();
		horizontalLayout.setSizeFull();
		horizontalLayout.setMargin(true);
		tabSheet.addTab(horizontalLayout, "HorizontalLayout");

		DesignerOverlayExtension layoutExt = DesignerOverlayExtension.create(horizontalLayout);
		layoutExt.setSupportsAlignments(false);
		layoutExt.setSupportsMargins(true);
		layoutExt.setSupportsSpacing(true);
		layoutExt.setSupportsPropertiesDialog(true);
		layoutExt.setSupportsRemove(false);
		layoutExt.setSupportsAdd(true);
		layoutExt.addAllEventHanndler(new DesignerOverlayExtension.AllEventHanndler() {
			@Override
			public void switchEditable(DesignerOverlayExtension.SwitchEditableEvent event) {
				horizontalLayout.setReadOnly(!horizontalLayout.isReadOnly());
			}

			public void switchMargin(DesignerOverlayExtension.SwitchMarginEvent event) {
				horizontalLayout.setMargin(horizontalLayout.getMargin().getBitMask() == 0);
			}

			public void switchSpacing(DesignerOverlayExtension.SwitchSpacingEvent event) {
				horizontalLayout.setSpacing(!horizontalLayout.isSpacing());
			}

			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}

			@Override
			public void addChild(AddChildEvent event) {
				addToHorizontalLayout(horizontalLayout, 10);
			}
		});

		addToHorizontalLayout(horizontalLayout, 0);
		addToHorizontalLayout(horizontalLayout, 1);
		addToHorizontalLayout(horizontalLayout, 2);
		addToHorizontalLayout(horizontalLayout, 3);
	}

	private void addToHorizontalLayout(final HorizontalLayout horizontalLayout, int index) {
		final TextField text = new TextField("Mouse over " + index);
		text.setId("Mouse over " + index);
		horizontalLayout.addComponent(text);

		DesignerOverlayExtension extension = DesignerOverlayExtension.create(text);
		extension.setSupportsAlignments(true);
		extension.setSupportsMargins(false);
		extension.setSupportsSpacing(false);
		extension.setSupportsPropertiesDialog(true);
		extension.setSupportsRemove(true);
		extension.setSupportsEditable(true);

		extension.addAllEventHanndler(new DesignerOverlayExtension.AllEventHanndler() {
			@Override
			public void alignmentChanged(DesignerOverlayExtension.AlignmentChangedEvent event) {
				AlignmentInfoUtil.apply(horizontalLayout, text, event.getAlignment());
			}

			@Override
			public void removeChild(RemoveChildEvent event) {
				horizontalLayout.removeComponent(event.getComponent());
			}

			@Override
			public void switchEditable(SwitchEditableEvent event) {
				text.setReadOnly(!text.isReadOnly());
			}

			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}
		});

		extension.getState().alignment = AlignmentInfo.TOP_CENTER;
		AlignmentInfoUtil.apply(horizontalLayout, text, AlignmentInfo.TOP_CENTER);
	}

	/**
	 * Add texts in horizontal layouts in verticallayout to the tabsheet.
	 * 
	 * @param tabSheet
	 */
	private void addLayoutInlayout(TabSheet tabSheet) {
		final VerticalLayout verticalLayout = new VerticalLayout();
		verticalLayout.setSizeFull();
		verticalLayout.setMargin(true);
		tabSheet.addTab(verticalLayout, "Layout in Layout");

		DesignerOverlayExtension layoutExt = DesignerOverlayExtension.create(verticalLayout);
		layoutExt.setSupportsAlignments(false);
		layoutExt.setSupportsMargins(true);
		layoutExt.setSupportsSpacing(true);
		layoutExt.setSupportsPropertiesDialog(true);
		layoutExt.setSupportsRemove(false);

		layoutExt.addAllEventHanndler(new DesignerOverlayExtension.AllEventHanndler() {

			@Override
			public void switchEditable(DesignerOverlayExtension.SwitchEditableEvent event) {
				verticalLayout.setReadOnly(!verticalLayout.isReadOnly());
			}

			@Override
			public void switchMargin(DesignerOverlayExtension.SwitchMarginEvent event) {
				verticalLayout.setMargin(verticalLayout.getMargin().getBitMask() == 0);
			}

			@Override
			public void switchSpacing(DesignerOverlayExtension.SwitchSpacingEvent event) {
				verticalLayout.setSpacing(!verticalLayout.isSpacing());
			}

			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}
		});

		addToLayoutInLayout(verticalLayout, 0);
		addToLayoutInLayout(verticalLayout, 1);
		addToLayoutInLayout(verticalLayout, 2);
		addToLayoutInLayout(verticalLayout, 3);
		addToLayoutInLayout(verticalLayout, 4);
		addToLayoutInLayout(verticalLayout, 5);
	}

	private void addToLayoutInLayout(final VerticalLayout verticalLayout, int index) {
		final HorizontalLayout hl = new HorizontalLayout();
		verticalLayout.addComponent(hl);

		DesignerOverlayExtension extension = DesignerOverlayExtension.create(hl);
		extension.setSupportsAlignments(true);
		extension.setSupportsMargins(true);
		extension.setSupportsSpacing(true);
		extension.setSupportsPropertiesDialog(true);
		extension.setSupportsRemove(true);

		extension.addAllEventHanndler(new DesignerOverlayExtension.AllEventHanndler() {
			@Override
			public void alignmentChanged(DesignerOverlayExtension.AlignmentChangedEvent event) {
				AlignmentInfoUtil.apply(verticalLayout, hl, event.getAlignment());
			}

			@Override
			public void removeChild(RemoveChildEvent event) {
				verticalLayout.removeComponent(event.getComponent());
			}
			
			@Override
			public void switchMargin(DesignerOverlayExtension.SwitchMarginEvent event) {
				hl.setMargin(hl.getMargin().getBitMask() == 0);
			}

			@Override
			public void switchSpacing(DesignerOverlayExtension.SwitchSpacingEvent event) {
				hl.setSpacing(!hl.isSpacing());
			}

			@Override
			public void switchEditable(SwitchEditableEvent event) {
				hl.setReadOnly(!hl.isReadOnly());
			}

			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}
		});

		extension.getState().alignment = AlignmentInfo.TOP_CENTER;
		AlignmentInfoUtil.apply(verticalLayout, hl, AlignmentInfo.TOP_CENTER);

		addToHorizontalLayoutNoAlignment(hl, 0);
		addToHorizontalLayoutNoAlignment(hl, 1);
		addToHorizontalLayoutNoAlignment(hl, 2);
		addToHorizontalLayoutNoAlignment(hl, 3);
		addToHorizontalLayoutNoAlignment(hl, 4);
		addToHorizontalLayoutNoAlignment(hl, 5);
	}

	private void addToHorizontalLayoutNoAlignment(final HorizontalLayout horizontalLayout, int index) {
		final TextField text = new TextField("Mouse over " + index);
		text.setId("Mouse over " + index);
		text.setSizeFull();
		horizontalLayout.addComponent(text);

		DesignerOverlayExtension extension = DesignerOverlayExtension.create(text);
		extension.setSupportsAlignments(false);
		extension.addAllEventHanndler(new DesignerOverlayExtension.AllEventHanndler() {
			@Override
			public void alignmentChanged(DesignerOverlayExtension.AlignmentChangedEvent event) {
				AlignmentInfoUtil.apply(horizontalLayout, text, event.getAlignment());
			}

			@Override
			public void removeChild(RemoveChildEvent event) {
				horizontalLayout.removeComponent(event.getComponent());
			}

			@Override
			public void switchEditable(SwitchEditableEvent event) {
				text.setReadOnly(!text.isReadOnly());
			}

			@Override
			public void showProperties(ShowPropertiesEvent event) {
				Notification.show("Requested properties dialog");
			}
		});

		AlignmentInfoUtil.apply(horizontalLayout, text, AlignmentInfo.FILL_FILL);
	}
}