/*
 *                                                                            
 *  Copyright (c) 2011 - 2017 - 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                                 
 *                                                                            
 *  Initial contribution:                                                      
 *     Loetz GmbH & Co. KG
 * 
 */
package org.eclipse.osbp.utils.vaadin;

import org.eclipse.osbp.ui.api.layout.IViewLayoutManager;
import org.eclipse.osbp.utils.theme.EnumCssClass;

import com.vaadin.server.Extension;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;

/**
 * The Class ViewLayoutManager.
 */
public class ViewLayoutManager implements IViewLayoutManager {
	private static final long serialVersionUID = 6497632074130627336L;
	private Label label;
	private ExtendedVerticalLayout workArea;
	private HorizontalLayout topArea;
	private HorizontalLayout multiArea;
	private VerticalLayout sideArea;
	private VerticalLayout dataArea;

	@Override
	public void init(AbstractOrderedLayout parent) {
		label = new Label();
		label.addStyleName(EnumCssClass.VIEW_HEADER_H2.toString());
		label.setSizeUndefined();

		topArea = new HorizontalLayout(label);
		topArea.addStyleName(EnumCssClass.TOP_AREA.toString());
		topArea.setSizeUndefined();
		
		sideArea = new VerticalLayout();
		sideArea.addStyleName(EnumCssClass.SIDE_AREA.toString());
	    sideArea.setSizeUndefined();

	    dataArea = new VerticalLayout();
	    dataArea.addStyleName(EnumCssClass.DATA_AREA.toString());
	    dataArea.setSizeFull();

	    multiArea = new HorizontalLayout(sideArea, dataArea);
	    multiArea.addStyleName(EnumCssClass.MULTI_AREA.toString());
	    multiArea.setSizeFull();
	    multiArea.setExpandRatio(dataArea, 1);

	    workArea = new ExtendedVerticalLayout();
		workArea.addStyleName(EnumCssClass.WORK_AREA.toString());
	    workArea.setSizeFull();
	    workArea.addComponent(topArea);
	    workArea.addComponent(multiArea);
	    workArea.setExpandRatio(multiArea, 1);

	    parent.setPrimaryStyleName("osbp");
	    parent.addStyleName(EnumCssClass.VIEW.toString());
	    parent.addComponent(workArea);
	    parent.setExpandRatio(workArea, 1);
	}

	@Override
	public void addExtension(Extension extension) {
		workArea.addExtension(extension);
	}

	@Override
	public void removeExtension(Extension extension) {
		workArea.removeExtension(extension);
	}

	@Override
	public void setLabelValue(String text) {
		if(text == null || text.isEmpty()) {
			label.setWidth("0px");
			label.setHeight("0px");
		} else {
			label.setValue(text);
		}
	}

	@Override
	public HorizontalLayout getTopArea() {
		return topArea;
	}

	@Override
	public VerticalLayout getSideArea() {
		return sideArea;
	}

	@Override
	public VerticalLayout getDataArea() {
		return dataArea;
	}
	
}
