/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.dhaval.web.vaadin.simple.forms;

import com.dhaval.web.vaadin.simple.EntryPoint.GenericFieldFactory;
import com.dhaval.web.vaadin.simple.EntryPoint.LoginDetail;
import com.dhaval.web.vaadin.simple.GenericForm;
import com.dhaval.web.vaadin.simple.GenericFormEventHandler;
import com.dhaval.web.vaadin.simple.GenericMap;
import com.dhaval.web.vaadin.simple.MapTable;
import com.dhaval.web.vaadin.simple.domain.Form;
import com.dhaval.web.vaadin.simple.domain.FormField;
import com.dhaval.web.vaadin.simple.domain.FormsContainer;
import com.vaadin.Application;
import com.vaadin.data.util.MethodProperty;
import com.vaadin.data.util.PropertysetItem;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author dhaval
 */
public class UserWindow extends Window {

    private Application app;
    private FormsContainer formContainer;

    private LoginDetail userDetail;

    public UserWindow(LoginDetail userDetail) {
        this.userDetail = userDetail;
        formContainer = new FormsContainer(userDetail);

        VerticalLayout vPanel = new VerticalLayout();
        vPanel.setSpacing(true);
        vPanel.setWidth("550px");

        Panel infoPanel = new Panel();
        infoPanel.addComponent(new Label("The application helps the logged-in user to create new entry forms, enter/save form data and query the saved data. All the information is saved in the Google BigTable using the Google App Engine DataStore Low-level API.", Label.CONTENT_XHTML));
        vPanel.addComponent(infoPanel);

        HorizontalLayout headerBar = new HorizontalLayout();
        headerBar.setSpacing(true);
        headerBar.addComponent(new Label("Guest"));

        Button logoutBtn = new Button("Logout", new Button.ClickListener() {

            public void buttonClick(ClickEvent event) {
                getApplication().close();
            }
        });
        logoutBtn.setStyleName(Button.STYLE_LINK);
        headerBar.addComponent(logoutBtn);
        vPanel.addComponent(headerBar);
        vPanel.addComponent(new Label("<hr>", Label.CONTENT_XHTML));

        TabSheet formTabs = new TabSheet();
        formTabs.addTab(getAvailableForms(), "Available Forms", null);
        formTabs.addTab(new FormDefinition(formContainer), "New Form", null);
        vPanel.addComponent(formTabs);

        Panel footer = new Panel();
        footer.addComponent(new Label("© <a href='http://twitter.com/dhavaln'>dhavaln</a>", Label.CONTENT_XHTML));
        footer.setWidth("100%");
        vPanel.addComponent(footer);

        addComponent(vPanel);
    }

    public Layout getAvailableForms() {
        final VerticalLayout vPanel = new VerticalLayout();
        vPanel.setSpacing(true);
        vPanel.setMargin(true);

        formContainer.addListener(new FormsContainer.FormListener() {

            public void changed() {
                vPanel.removeAllComponents();
                List<Form> forms = formContainer.getAvailableForms();
                for (final Form form : forms) {
                    Panel formPanel = new Panel();

                    VerticalLayout hPanel = new VerticalLayout();
                    Label formLbl = new Label("<div style='font-family: verdana; font-size: 1.2em; font-weight: bold;'>" + form.getName() + "</div>", Label.CONTENT_XHTML);
                    hPanel.addComponent(formLbl);
                    hPanel.addComponent(new Label("<div style='font-style: italic;'>" + form.getDescription() + "</div>", Label.CONTENT_XHTML));

                    HorizontalLayout btnPanel = new HorizontalLayout();
                    btnPanel.setSpacing(true);
                    Button enterDataBtn = new Button("Enter Data");
                    enterDataBtn.addListener(new Button.ClickListener() {

                        public void buttonClick(ClickEvent event) {
                            try {
                                Set<FormField> fields = form.getFields();
                                Map<String, Object> fieldMap = new GenericMap();
                                Map<String, String> typeMap = new HashMap<String, String>();

                                PropertysetItem items = new PropertysetItem();
                                for (FormField field : fields) {
                                    fieldMap.put(field.getName(), null);

                                    Class type = Object.class;
                                    String getMathod = "get";
                                    String putMathod = "put";
                                    if (field.getType().equalsIgnoreCase("string")) {
                                        type = String.class;
                                        getMathod = "getString";
                                        putMathod = "putString";
                                    } else if (field.getType().equalsIgnoreCase("number")) {
                                        type = Double.class;
                                        getMathod = "getNumber";
                                        putMathod = "putNumber";
                                    } else if (field.getType().equalsIgnoreCase("date")) {
                                        type = Date.class;
                                        getMathod = "getDate";
                                        putMathod = "putDate";
                                    }

                                    items.addItemProperty(field.getName(),
                                            new MethodProperty(type, fieldMap, getMathod, putMathod, new String[]{field.getName()}, new Object[]{field.getName(), null}, 1));

                                    typeMap.put(field.getName(), field.getType());
                                }

                                final Window beanWindow = getEmptyWindow(form.getName() + " Form");
                                GenericForm beanForm = new GenericForm(fieldMap, items, form.getName(), new GenericFieldFactory(typeMap), new GenericFormEventHandler() {

                                    public void formCommitted(Object formBean) {
                                        try {
                                            formContainer.addData(form.getName(), (Map) formBean);
                                            getWindow().removeWindow(beanWindow);
                                            Notification not = new Notification("Data successfully saved.", "", Notification.TYPE_HUMANIZED_MESSAGE);
                                            getWindow().showNotification(not);
                                        } catch (Exception e) {
                                            Notification not = new Notification("Error", e.getMessage(), Notification.TYPE_ERROR_MESSAGE);
                                            getWindow().showNotification(not);
                                        }
                                    }
                                });
                                beanWindow.setContent(beanForm);
                                getWindow().addWindow(beanWindow);
                            } catch (Exception e) {
                                Notification not = new Notification("Error", e.getMessage(), Notification.TYPE_ERROR_MESSAGE);
                                getWindow().showNotification(not);
                            }
                        }
                    });
                    enterDataBtn.setStyleName(Button.STYLE_LINK);
                    btnPanel.addComponent(enterDataBtn);

                    Button viewDataBtn = new Button("View Data");
                    viewDataBtn.setStyleName(Button.STYLE_LINK);
                    viewDataBtn.addListener(new Button.ClickListener() {

                        public void buttonClick(ClickEvent event) {
                            Window viewWindow = getEmptyWindow(form.getName());
                            List<Map<String, Object>> dataList = formContainer.getFormData(form.getName());

                            if (dataList == null || dataList.isEmpty()) {
                                Notification not = new Notification("No data available", Notification.TYPE_HUMANIZED_MESSAGE);
                                getWindow().showNotification(not);
                                return;
                            }

                            MapTable mapTable = new MapTable(dataList);
                            viewWindow.setContent(mapTable);
                            getWindow().addWindow(viewWindow);
                        }
                    });
                    btnPanel.addComponent(viewDataBtn);
                    hPanel.addComponent(btnPanel);

                    formPanel.addComponent(hPanel);
                    vPanel.addComponent(formPanel);
                }
            }
        });

        return vPanel;
    }

    public Window getEmptyWindow(String header) {
        Window formWindow = new Window(header);
        formWindow.setModal(true);
        formWindow.setClosable(true);
        formWindow.setWidth("30%");
        return formWindow;
    }
}
