/*
 * EntryPoint.java
 *
 * Created on April 6, 2010, 6:51 PM
 */
package com.dhaval.web.vaadin.simple;

import com.dhaval.web.vaadin.simple.forms.UserWindow;
import com.dhaval.web.vaadin.simple.validators.IntegerValidator;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.vaadin.Application;
import com.vaadin.data.Item;
import com.vaadin.data.validator.DoubleValidator;
import com.vaadin.ui.*;
import com.vaadin.ui.Button.ClickEvent;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;

/** 
 *
 * @author dhaval
 * @version 
 */
public class EntryPoint extends Application {

    public EntryPoint() {
    }

    @Override
    public void init() {
        Window mainWindow = new Window("Vaadin Demo Application");
        mainWindow.center();

        GenericForm loginForm = new GenericForm(new LoginDetail(), "Sign in", new GenericFieldFactory(), new GenericFormEventHandler() {

            public void formCommitted(Object formBean) {
                LoginDetail loginDetail = (LoginDetail) formBean;

                Query userQuery = new Query("user");
                userQuery.addFilter("username", Query.FilterOperator.EQUAL, loginDetail.getUserId());
                userQuery.addFilter("password", Query.FilterOperator.EQUAL, loginDetail.getPassword());

                DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
                PreparedQuery query = datastore.prepare(userQuery);
                if(query.countEntities() >= 1){
                    UserWindow userWindow = new UserWindow(loginDetail);
                    EntryPoint.this.removeWindow(getMainWindow());
                    EntryPoint.this.setMainWindow(userWindow);
                }else{
                    Window.Notification not = new Window.Notification("", "Invalid Username or Password. Please try again.", Window.Notification.TYPE_ERROR_MESSAGE);
                    getMainWindow().showNotification(not);
                }
            }
        });

        VerticalLayout hPanel = new VerticalLayout();
        hPanel.setWidth("650px");
        hPanel.setSpacing(true);
        
        Panel panel = new Panel();
        Label lbl = new Label("This is a demostration application built using modern Java Web Framework - Vaadin. " +
                "For more information on Vaadin visit the product site <a href='http://vaadin.com'>Vaadin</a>. " +
                "Register for the login." +
                "<br><br>Application and Source is maintained by &copy<a href='http://twitter.com/dhavaln'>dhavaln</a>",
                Label.CONTENT_XHTML);
        panel.addComponent(lbl);

        hPanel.addComponent(panel);
        hPanel.setComponentAlignment(panel, Alignment.MIDDLE_CENTER);

        hPanel.addComponent(loginForm);
        hPanel.setComponentAlignment(loginForm, Alignment.MIDDLE_RIGHT);

        Button newUser = new Button("New User?", new Button.ClickListener() {

            public void buttonClick(ClickEvent event) {
                final Window formWindow = new Window("User Detail");
                formWindow.setModal(true);
                formWindow.setClosable(true);
                formWindow.setWidth("40%");

                GenericForm registrationForm = new GenericForm(new UserRegistration(), "New User", new GenericFieldFactory(), new GenericFormEventHandler() {

                    public void formCommitted(Object formBean) {
                        UserRegistration regInfo = (UserRegistration) formBean;
                        Query userQuery = new Query("user");
                        userQuery.addFilter("username", Query.FilterOperator.EQUAL, regInfo.getUserId());
                        userQuery.addFilter("password", Query.FilterOperator.EQUAL, regInfo.getPassword());

                        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
                        PreparedQuery query = datastore.prepare(userQuery);
                        if(query.countEntities() > 0){
                            getMainWindow().showNotification("User Id already available. Try selecting another one", Window.Notification.TYPE_ERROR_MESSAGE);
                        }else{
                            Entity newUser = new Entity("user", regInfo.getUserId());
                            newUser.setProperty("username", regInfo.getUserId());
                            newUser.setProperty("password", regInfo.getPassword());
                            datastore.put(newUser);
                            getMainWindow().removeWindow(formWindow);
                            getMainWindow().showNotification("Requested user has been created", Window.Notification.TYPE_HUMANIZED_MESSAGE);
                        }
                    }
                });

                formWindow.addComponent(registrationForm);
                getMainWindow().addWindow(formWindow);
            }
        });
        newUser.setStyleName(Button.STYLE_LINK);

        hPanel.addComponent(new Label("<hr>", Label.CONTENT_XHTML));
        hPanel.addComponent(newUser);
        
        mainWindow.addComponent(hPanel);

        setMainWindow(mainWindow);
    }

    public static class UserRegistration implements Serializable{
        private String userId;
        private String password;

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public String getUserId() {
            return userId;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }

    }

    public static class LoginDetail implements Serializable{

        private String userId;
        private String password;
        private boolean rememberMe;

        public void setPassword(String password) {
            this.password = password;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }

        public String getPassword() {
            return password;
        }

        public String getUserId() {
            return userId;
        }

        public void setRememberMe(boolean rememberMe) {
            this.rememberMe = rememberMe;
        }

        public boolean isRememberMe() {
            return rememberMe;
        }
    }

    public static class GenericFieldFactory extends DefaultFieldFactory implements Serializable{

        private Map<String, String> fieldType;
        private List<String> listFields;

        public GenericFieldFactory() {
        }

        public GenericFieldFactory(Map<String, String> fieldType) {
            this.fieldType = fieldType;
        }

        public GenericFieldFactory(List<String> listFields){
            this.listFields = listFields;
        }
        
        @Override
        public Field createField(Item item, Object propertyId, Component uiContext) {
            Class type = item.getItemProperty(propertyId).getType();
            Field field = null;
            if(fieldType != null && !fieldType.isEmpty()){
                String strType = fieldType.get(propertyId.toString());
                if(strType.equalsIgnoreCase("string")){
                    type = String.class;
                }else if(strType.equalsIgnoreCase("number")){
                    type = Double.class;
                    item.getItemProperty(propertyId).setValue(0.0);
                }
            }

            if (listFields != null && listFields.contains(propertyId.toString())) {
                ComboBox cb = new ComboBox(propertyId.toString());
                cb.addItem("String");
                cb.addItem("Number");
                cb.addItem("Date");
                cb.setNewItemsAllowed(false);

                field = cb;
                field.setPropertyDataSource(item.getItemProperty(propertyId));
            }

            if (item.getItemProperty(propertyId).getValue() == null
                    && (type == String.class
                    || type == Object.class) ) {
                item.getItemProperty(propertyId).setValue("");
            }

            if(field == null){
                field = super.createField(item, propertyId, uiContext);
            }
            field.setRequired(true);

            if (type == StringBuffer.class) {
                TextField tf = (TextField) field;
                tf.setWordwrap(true);
                tf.setRows(5);
                tf.setColumns(25);
            }

            if(field instanceof TextField){
                TextField tf = (TextField) field;
                if(propertyId.toString().toLowerCase().indexOf("password") >= 0){
                    tf.setSecret(true);
                }
            }

            if (type == Integer.class) {
                field.addValidator(new IntegerValidator("value must be a number"));
            } else if (type == Double.class) {
                field.addValidator(new DoubleValidator("value must be a number"));
            } else if (type == Date.class){
                DateField df = (DateField) field;
                df.setResolution(DateField.RESOLUTION_MIN);
            }

            return field;
        }
    }
}
