/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.essar.mes.sap.log.client;

import com.essar.mes.sap.log.client.data.ServiceLogData;
import com.essar.mes.sap.log.client.data.ServiceLogField;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.Autofit;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.Side;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.types.VisibilityMode;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Dialog;
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.events.CloseClientEvent;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.ValuesManager;
import com.smartgwt.client.widgets.form.fields.DateItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextAreaItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
import com.smartgwt.client.widgets.form.validator.CustomValidator;
import com.smartgwt.client.widgets.form.validator.DateRangeValidator;
import com.smartgwt.client.widgets.form.validator.Validator;
import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.HeaderSpan;
import com.smartgwt.client.widgets.grid.HoverCustomizer;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.SectionStack;
import com.smartgwt.client.widgets.layout.SectionStackSection;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.menu.Menu;
import com.smartgwt.client.widgets.menu.MenuItem;
import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent;
import com.smartgwt.client.widgets.tab.Tab;
import com.smartgwt.client.widgets.tab.TabSet;
import com.smartgwt.client.widgets.toolbar.ToolStrip;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Main entry point.
 *
 * @author dhaval
 */
public class viewerEntryPoint implements EntryPoint {

    private LinkedHashMap serviceMap;
    private ListGrid logGrid, fieldList, validationList, returnFieldList, pivotList;
    private ServiceLogAsync logService;
    private String serviceId;

    /**
     * Creates a new instance of viewerEntryPoint
     */
    public viewerEntryPoint() {
        serviceMap = new LinkedHashMap();
        serviceMap.put("INVENTORY", "Inventory");
        serviceMap.put("ORDER", "Order");
        serviceMap.put("MRP", "MRP");
        serviceMap.put("NONE", "");

        logService = (ServiceLogAsync) GWT.create(ServiceLog.class);
        ServiceDefTarget target = (ServiceDefTarget) logService;
        target.setServiceEntryPoint(GWT.getModuleBaseURL() + "log.rpc");
    }

    /** 
     * The entry point method, called automatically by loading a module
     * that declares an implementing class as an entry-point
     */
    public void onModuleLoad() {
        HLayout mainLayout = new HLayout();
        mainLayout.setWidth100();
        mainLayout.setHeight100();
        
        logGrid = getLogGrid();
        ListGrid detailGrid = getLogDetailTabset();

        mainLayout.addMember(logGrid);
        mainLayout.addMember(detailGrid);

        SectionStack mainStack = new SectionStack();
        mainStack.setWidth100();
        mainStack.setHeight100();
        mainStack.setVisibilityMode(VisibilityMode.MULTIPLE);
        mainStack.setAnimateSections(true);
        
        SectionStackSection searchSection = new SectionStackSection("Select Service");
        searchSection.addItem(getServiceSelection());
        searchSection.setExpanded(Boolean.TRUE);

        SectionStackSection detailSection = new SectionStackSection("Log Detail");
        detailSection.addItem(mainLayout);
        detailSection.setExpanded(Boolean.TRUE);
        detailSection.setCanCollapse(Boolean.FALSE);
        
        mainStack.addSection(searchSection);
        mainStack.addSection(detailSection);

        mainStack.setMargin(10);
        mainStack.draw();
    }

    private Canvas getServiceSelection(){
        Canvas canvas = new Canvas();

        ValuesManager vm = new ValuesManager();

        VLayout layout = new VLayout();
        layout.setWidth100();
        layout.setHeight100();
        layout.setMargin(5);
        
        final SelectItem selectItem = new SelectItem("SERVICES");
        selectItem.setValueMap(serviceMap);
        selectItem.setTitle("Select Service");

        CustomValidator selectValidator = new CustomValidator() {

            @Override
            protected boolean condition(Object value) {
//                SC.say(value.toString());
                if(value.toString().equalsIgnoreCase("NONE")){
                    return false;
                }else{
                    return true;
                }
            }
        };
        selectValidator.setErrorMessage("Please select a service");
        selectItem.setValidators(new Validator[]{selectValidator});

        final DateItem startDate = new DateItem("START_DATE");
        startDate.setTitle("Start Date");
        startDate.setUseTextField(true);
        startDate.setValue(new Date());

        final DateItem endDate = new DateItem("END_DATE");
        endDate.setTitle("End Date");
        endDate.setUseTextField(true);

        Date tomorrow = new Date();
        tomorrow.setTime(tomorrow.getTime() + (60 * 60 * 24 * 1000));
        endDate.setValue(tomorrow);

        CustomValidator startDateValidator = new CustomValidator() {

            @Override
            protected boolean condition(Object value) {
                Date d1 = (Date) startDate.getValue();
                Date d2 = (Date) endDate.getValue();

                if(d1.getTime() > d2.getTime()){
                    return false;
                }

                return true;
            }
        };
        startDateValidator.setErrorMessage("Start date is exceeding End date");
        startDate.setValidators(new Validator[]{startDateValidator});

        final DynamicForm filterForm = new DynamicForm();
        filterForm.setNumCols(6);
        filterForm.setAutoFocus(false);
        filterForm.setValuesManager(vm);

        filterForm.setFields(selectItem, startDate, endDate);
        filterForm.setWidth("80%");

        layout.addMember(filterForm);

        IButton search = new IButton("Search");
        search.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                serviceId =  selectItem.getValue().toString();

                AsyncCallback callback = new AsyncCallback() {

                    public void onFailure(Throwable caught) {
                        SC.say(serviceId, "Error while loading service data." + caught.getMessage());
                    }

                    public void onSuccess(Object result) {
                        List<ServiceLogData> serviceData = (List<ServiceLogData>) result;
                        ListGridRecord[] records = new ListGridRecord[serviceData.size()];
                        int i = 0;
                        for (ServiceLogData data : serviceData) {
                            records[i] = new ListGridRecord();
                            records[i].setAttribute("ID", data.getId());
                            records[i].setAttribute("CALL_DATE", data.getCallDate());
                            records[i].setAttribute("RETURN_DATE", data.getReturnDate());
                            records[i].setAttribute("CALL_TIME", data.getCallTime());
                            records[i].setAttribute("RETURN_TIME", data.getReturnTime());
                            records[i].setAttribute("REMOTE", data.getRemoteAddress());
                            i++;
                        }
                        logGrid.setRecords(records);
                    }
                };

//                SC.say("Selected Item, Start Date, End Date" + serviceId + ", "+ startDate.getValue().toString() + ", " + endDate.getValue().toString());
                filterForm.validate();
                if (!filterForm.hasErrors()) {
                    logService.getLog(serviceId, callback);
                }
            }
        });

        layout.addMember(search);
        
        canvas.addChild(layout);
        return canvas;
    }

    private ListGrid getLogGrid(){
        ListGrid logGrid1 = new ListGrid();
        logGrid1.setFields(
                new ListGridField("ID", "CALL ID"),
                new ListGridField("CALL_DATE", "Call Date"),
                new ListGridField("CALL_TIME", "Call Time"),
                new ListGridField("RETURN_TIME", "Return Time"),
                new ListGridField("RETURN_DATE", "Return Date"),
                new ListGridField("REMOTE", "Remote Address"));
        logGrid1.setShowResizeBar(true);
        logGrid1.setWidth("20%");
        logGrid1.setGroupByField("CALL_DATE");
        logGrid1.getField("ID").setHidden(true);
        logGrid1.getField("CALL_DATE").setHidden(true);
        logGrid1.getField("RETURN_DATE").setHidden(true);
        
        
        logGrid1.addRecordClickHandler(new RecordClickHandler() {

            public void onRecordClick(RecordClickEvent event) {
                String recordId = event.getRecord().getAttribute("ID");

                AsyncCallback fieldCallback = new AsyncCallback() {

                    public void onFailure(Throwable caught) {
                        SC.say("Error while loading fields.");
                    }

                    public void onSuccess(Object result) {
                        ServiceLogData serviceData = (ServiceLogData) result;

                        List<ListGridField> pivotReturnFieldList = new ArrayList<ListGridField>();
                        List<ListGridField> pivotFieldList = new ArrayList<ListGridField>();
                        Map<Integer, Map> pivotValueMap = new LinkedHashMap<Integer, Map>();

                        List<ServiceLogField> fields = serviceData.getFields();
                        List<ServiceLogField> returnFields = serviceData.getReturnFields();

                        int i = 0;
                        int rowCount = -1;
                        String[] receivedFieldHeader = new String[fields.size()];

                        for (ServiceLogField data : fields) {

                            if (!pivotValueMap.containsKey(data.getRecordNo())) {
                                pivotValueMap.put(data.getRecordNo(), new LinkedHashMap());
                                pivotValueMap.get(data.getRecordNo()).put("ID", data.getRecordId());
                                pivotValueMap.get(data.getRecordNo()).put("NO", data.getRecordNo());
                            }

                            pivotValueMap.get(data.getRecordNo()).put(data.getName(), data.getValue());

                            if (pivotValueMap.get(data.getRecordNo()).containsKey("validations")) {
                                pivotValueMap.get(data.getRecordNo()).put("validations", pivotValueMap.get(data.getRecordNo()).get("validations") + "," + data.getValidationError());
                            } else {
                                pivotValueMap.get(data.getRecordNo()).put("validations", data.getValidationError());
                            }

                            if (rowCount == -1) {
                                rowCount = data.getRecordNo();
                            }
                            if (rowCount == data.getRecordNo()) {
                                ListGridField gridField = new ListGridField(data.getName(), 100);
                                gridField.setType(ListGridFieldType.TEXT);
                                receivedFieldHeader[i] = data.getName();

                                pivotFieldList.add(gridField);
                            }

                            i++;
                        }

                        i=0;
                        for (ServiceLogField data : returnFields) {

                            if (!pivotValueMap.containsKey(data.getRecordNo())) {
                                pivotValueMap.put(data.getRecordNo(), new LinkedHashMap());
                                pivotValueMap.get(data.getRecordNo()).put("ID", data.getRecordId());
                                pivotValueMap.get(data.getRecordNo()).put("NO", data.getRecordNo());
                            }

                            pivotValueMap.get(data.getRecordNo()).put(data.getName(), data.getValue());

                            if (data.getValidationError() != null && data.getValidationError().length() > 0) {
                                if (pivotValueMap.get(data.getRecordNo()).containsKey("validations")) {
                                    pivotValueMap.get(data.getRecordNo()).put("validations", pivotValueMap.get(data.getRecordNo()).get("validations") + "," + data.getValidationError());
                                } else {
                                    pivotValueMap.get(data.getRecordNo()).put("validations", data.getValidationError());
                                }
                            }

                            if (rowCount == -1) {
                                rowCount = data.getRecordNo();
                            }
                            if (rowCount == data.getRecordNo()) {
                                ListGridField gridField = new ListGridField(data.getName(), 100);
                                gridField.setType(ListGridFieldType.TEXT);
                                receivedFieldHeader[i] = data.getName();

                                pivotFieldList.add(gridField);
                            }

                            i++;
                        }

                        List<ListGridField> pivotGridFields = new ArrayList<ListGridField>();

                        ListGridField id = new ListGridField("ID", "ID");
                        id.setFrozen(Boolean.TRUE);
                        id.setHidden(true);
                        id.setWidth(100);
                        pivotGridFields.add(id);

                        HoverCustomizer validationHover = new HoverCustomizer() {
                            public String hoverHTML(Object value, ListGridRecord record, int rowNum, int colNum) {
                                String[] validations = record.getAttribute("validations").split(",");
                                String style = "<b>Validations Errors</b>";
                                style += "<ul>";
                                for(String valid : validations){
                                    if(valid.length() > 0){
                                        style += "<li>" + valid + "</li>";
                                    }
                                }
                                style += "</ul>";
                                return style;
                            }
                        };
                        
                        ListGridField no = new ListGridField("NO","RECORD NO");
                        no.setShowHover(true);
                        no.setHoverCustomizer(validationHover);
                        no.setFrozen(Boolean.TRUE);
                        no.setWidth(100);
                        pivotGridFields.add(no);

                        pivotGridFields.addAll(pivotFieldList);

                        ListGridField validations = new ListGridField("validations", "Validation Errors");
                        validations.setShowHover(true);
                        validations.setHoverCustomizer(validationHover);
                        validations.setWidth(100);

                        pivotGridFields.add(validations);
                        pivotGridFields.addAll(pivotReturnFieldList);

                        ListGridRecord[] gridData = new ListGridRecord[pivotValueMap.size()];
                        Iterator valueMap = pivotValueMap.values().iterator();
                        i = 0;
                        while (valueMap.hasNext()) {
                            Map rowMap = (Map) valueMap.next();
                            gridData[i] = new ListGridRecord();

                            Iterator<String> valueField = (Iterator<String>) rowMap.keySet().iterator();

                            while (valueField.hasNext()) {
                                String fieldName = valueField.next();
                                Object fieldValue = rowMap.get(fieldName);

                                gridData[i].setAttribute(fieldName, fieldValue);
                            }
                            i++;
                        }

                        pivotList.setFields(pivotGridFields.toArray(new ListGridField[0]));
                        pivotList.setRecords(gridData);
                        SC.clearPrompt();
                    }
                };
                logService.getLogDetail(serviceId, recordId, fieldCallback);
                SC.showPrompt("Contacting Server...");
            }
        });
        return logGrid1;
    }

    private ListGrid getLogDetailTabset() {
        TabSet logDetailTabSet = new TabSet();
        logDetailTabSet.setTabBarPosition(Side.TOP);

        Tab fieldsTab = new Tab("Fields");
        fieldList = new ListGrid();
        fieldList.setFields(
                new ListGridField("NO", "RECORD NO"),
                new ListGridField("NAME", "NAME"),
                new ListGridField("VALUE", "VALUE"));
        fieldList.setGroupByField("NO");
        fieldList.getField("NO").setHidden(true);
        fieldsTab.setPane(fieldList);

        Tab validationsTab = new Tab("Validation Errors");
        validationList = new ListGrid();
        validationList.setFields(
                new ListGridField("NO", "RECORD NO"),
                new ListGridField("NAME", "NAME"),
                new ListGridField("VALUE", "VALUE"),
                new ListGridField("ERROR", "ERROR"));
        validationList.setGroupByField("NO");
        validationList.getField("NO").setHidden(true);
        validationsTab.setPane(validationList);

        Tab returnFieldsTab = new Tab("Return Fields");
        returnFieldList = new ListGrid();
        returnFieldList.setFields(
                new ListGridField("NO", "RECORD NO"),
                new ListGridField("NAME", "NAME"),
                new ListGridField("VALUE", "VALUE"));
        returnFieldList.setGroupByField("NO");
        returnFieldList.getField("NO").setHidden(true);
        returnFieldsTab.setPane(returnFieldList);

        Tab pivotTab = new Tab("Log Data");
        
        pivotList = new ListGrid();
        pivotList.setHoverWidth(300);
        pivotList.setAlternateRecordStyles(true);
        pivotList.setEmptyMessage("<br>Select a <b>Service</b> to populate this grid.");

        Menu menu = new Menu();
        menu.setShowShadow(true);
        menu.setShadowDepth(10);
        
        MenuItem newItem = new MenuItem("Show Validation Errors", "icons/16/document_plain_new.png");
        newItem.addClickHandler(new com.smartgwt.client.widgets.menu.events.ClickHandler() {

            public void onClick(MenuItemClickEvent event) {
                if (pivotList.anySelected()) {
                    String[] validations = pivotList.getSelectedRecord().getAttribute("validations").split(",");
                    try {
                        final Window winModal = new Window();
                        winModal.setWidth(400);
                        winModal.setHeight(200);
                        winModal.setTitle("Validation Errors");
                        winModal.setShowMinimizeButton(false);
                        winModal.setIsModal(true);
                        winModal.centerInPage();
                        winModal.setCanDragResize(Boolean.TRUE);
                        winModal.addCloseClickHandler(new CloseClickHandler() {

                            public void onCloseClick(CloseClientEvent event) {
                                winModal.destroy();
                            }
                        });

                        ListGrid errorGrid = new ListGrid();
                        errorGrid.setWidth100();
                        errorGrid.setHeight100();
                        errorGrid.setCanGroupBy(false);
                        errorGrid.setCanSort(false);
                        errorGrid.setShowHeader(false);
                        errorGrid.setAutoFitData(Autofit.HORIZONTAL);
                        
                        ListGridField errorField = new ListGridField("error", "Error");
                        ListGridField noField = new ListGridField("no", "Sr No");
                        noField.setWidth("10%");
                        errorGrid.setFields(noField, errorField);

                        ListGridRecord[] errors = new ListGridRecord[validations.length];
                        int i = 0;
                        for (String error : validations) {
                            if (error.length() > 0) {
                                errors[i] =new ListGridRecord();
                                errors[i].setAttribute("no", (i+1));
                                errors[i].setAttribute("error", error);
                                i++;
                            }
                        }
                        errorGrid.setRecords(errors);

                        winModal.addItem(errorGrid);
                        winModal.show();
                    } catch (Exception e) {
                        SC.say(e.getMessage());
                    }
                }
            }
        });

        menu.setItems(newItem);
        
        pivotList.setContextMenu(menu);

        pivotTab.setPane(pivotList);
        logDetailTabSet.addTab(pivotTab);
        return pivotList;
    }
}
