/*
 * Copyright
 *   2009 axYus - www.axyus.com
 *   2009 C.Marchand - christophe.marchand@axyus.com
 *
 * This file is part of XEMELIOS.
 *
 * XEMELIOS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * XEMELIOS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package fr.gouv.finances.dgfip.xemelios.web.gwt.client.widget;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import fr.gouv.finances.dgfip.xemelios.web.gwt.client.dto.DisplayableFieldDTO;
import fr.gouv.finances.dgfip.xemelios.web.gwt.client.dto.ListResultatDTO;
import fr.gouv.finances.dgfip.xemelios.web.gwt.client.service.ServiceLocator;
import fr.gouv.finances.dgfip.xemelios.web.gwt.client.utils.GWTUtils;
import fr.gouv.finances.dgfip.xemelios.web.gwt.client.widget.search.SearchWidget;

/**
 *
 * @author chm
 */
public class DlgSearchParams extends DialogBox {
    private static final String LBL_PRIMARY_STYLE_NAME = "selectable-listentry";
    private static final String LBL_SELECTED_STYLE = "selected";
    private static final String SCROLLPANE_STYLE_NAME = "gwt-BorderedScollPanel";

    public static final transient String DLG_TITLE = "Tris et champs affich&eacute;s";

    private SearchWidget parent;

    private ListResultatDTO lr;

    public DlgSearchParams(SearchWidget parent, ListResultatDTO lr) {
        super(false, true);
        setText(new HTML(DLG_TITLE).getHTML());
        this.parent = parent;
        this.lr = lr;
        initComponents();
    }

    private void initComponents() {
        VerticalPanel mainPane = new VerticalPanel();
        TabPanel tab = new TabPanel();
        Widget fieldsTab;
        tab.add(fieldsTab = createDisplayableFieldsTab(), "Champs");
        tab.add(createSortableFieldsTab(),"Tris");
        tab.selectTab(tab.getWidgetIndex(fieldsTab));
        mainPane.add(tab);
        mainPane.add(new ButtonBar(this));

        setWidget(mainPane);
        center();
    }

    protected void okClicked() {
        for(DisplayableFieldDTO field:lr.getDisplayableFields()) {
            if(field.getSortPosition()>=0 && !field.isDisplay()) {
                Window.alert(new HTML("Vous ne pouvez pas trier suivant un champ qui n'est pas affiché: "+field.getLibelle()).getHTML());
                break;
            }
        }
        saveSearchParams();
    }
    protected void cancelClicked() {
        hide();
    }
    protected Widget createDisplayableFieldsTab() {
        return new DisplayableFieldsPanel(lr);
    }
    protected Widget createSortableFieldsTab() {
        return new SortableFieldsPanel(lr);
    }
    protected void saveSearchParams() {
        ServiceLocator.getXemeliosService().setListResultatDTO(parent.getSearchSessionId(), lr, new AsyncCallback<String>() {
            public void onFailure(Throwable caught) {
                Window.alert(caught.getMessage());
            }
            public void onSuccess(String result) {
                if(result==null) hide();
                else Window.alert(result);
            }
        });
    }


    /**
     * The first tab
     */
    protected class DisplayableFieldsPanel extends HorizontalPanel {
        private ListResultatDTO lr;
        private int selectedCount= 0;
        private ImageButton buttonUp, buttonDown;
        private VerticalPanel list;
        public DisplayableFieldsPanel(ListResultatDTO lr) {
            super();
            this.lr=lr;
            ScrollPanel scroller = new ScrollPanel();
            scroller.setSize("250","300");
            list = new VerticalPanel();
            for(DisplayableFieldDTO field:lr.getDisplayableFields()) {
                list.add(new DisplayableField(field,this));
            }
            scroller.add(list);
            add(scroller);
            scroller.addStyleName(SCROLLPANE_STYLE_NAME);
            VerticalPanel vp = new VerticalPanel();
            buttonUp = new ImageButton(GWTUtils.getContextPath()+"/img/bt_up.png", GWTUtils.getContextPath()+"img/bt_up_deactivated.png", "Monter");
            buttonUp.setEnable(false);
            vp.add(buttonUp);
            buttonDown = new ImageButton(GWTUtils.getContextPath()+"/img/bt_down.png", GWTUtils.getContextPath()+"img/bt_down_deactivated.png", "Descendre");
            buttonDown.setEnable(false);
            vp.add(buttonDown);
            add(vp);
            buttonUp.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    buttonUpPressed();
                }
            });
            buttonDown.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    buttonDownPressed();
                }
            });
        }
        protected void notifySelectionChanged(boolean newValue) {
            if(newValue) selectedCount++;
            else selectedCount--;
            buttonDown.setEnable(selectedCount>0);
            buttonUp.setEnable(selectedCount>0);
        }
        protected void buttonUpPressed() {
            for(int i=1;i<list.getWidgetCount();i++) {
                Widget wd = list.getWidget(i);
                if(wd instanceof DisplayableField) {
                    DisplayableField df = (DisplayableField)wd;
                    if(df.isSelected()) {
                        list.remove(i);
                        list.insert(wd, i-1);
                        DisplayableFieldDTO field = lr.getDisplayableFields().remove(i);
                        lr.getDisplayableFields().add(i-1, field);
                    }
                }
            }
        }
        protected void buttonDownPressed() {
            for(int i=list.getWidgetCount()-2;i>=0;i--) {
                Widget wd = list.getWidget(i);
                if(wd instanceof DisplayableField) {
                    DisplayableField df = (DisplayableField)wd;
                    if(df.isSelected()) {
                        list.remove(i);
                        list.insert(wd, i+1);
                        DisplayableFieldDTO field = lr.getDisplayableFields().remove(i);
                        lr.getDisplayableFields().add(i+1, field);
                    }
                }
            }
        }
    }
    /**
     * The elements that are in the first tab (displayable fields), into the listbox
     */
    protected class DisplayableField extends HorizontalPanel {
        private DisplayableFieldDTO dto;
        private boolean selected = false;
        private CheckBox chk;
        private Label lbl;
        private DisplayableFieldsPanel parentPane;
        public DisplayableField(DisplayableFieldDTO dto, DisplayableFieldsPanel parentPane) {
            super();
            setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
            this.dto=dto;
            this.parentPane=parentPane;
            chk = new CheckBox();
            chk.setChecked(dto.isDisplay());
            add(chk);
            lbl = new Label(dto.getLibelle());
            chk.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    DisplayableField.this.dto.setDisplay(chk.isChecked());
                }
            });
            lbl.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    DisplayableField.this.onSelect();
                }
            });
            lbl.setStylePrimaryName(LBL_PRIMARY_STYLE_NAME);
            add(lbl);
        }
        private void onSelect() {
            selected = !selected;
            if(selected) {
                lbl.setStyleName(LBL_PRIMARY_STYLE_NAME+"-"+LBL_SELECTED_STYLE);
            } else {
                lbl.setStyleName(LBL_PRIMARY_STYLE_NAME);
            }

            parentPane.notifySelectionChanged(selected);
        }
        public boolean isSelected() { return selected; }
    }
    /**
     * The second tab
     */
    protected class SortableFieldsPanel extends HorizontalPanel {
        private ListResultatDTO lr;
        private VerticalPanel leftList;
        private VerticalPanel rightList;
        private int leftSelectedCount = 0;
        protected int rightSelectedCount = 0;
        private MoveButtonBar moveButtonBar;
        private SortButtonBar sortButtonBar;
        public SortableFieldsPanel(ListResultatDTO lr) {
            super();
            this.lr=lr;
            _sfp_initComponents();
        }
        private void _sfp_initComponents() {
            ScrollPanel leftScroller = new ScrollPanel();
            leftScroller.setSize("150", "300");
            leftList = new VerticalPanel();
            for(DisplayableFieldDTO field:lr.getDisplayableFields()) {
                if(field.getSortPosition()==DisplayableFieldDTO.SORT_POSITION_NO_SORT) {
                    leftList.add(new SortableField(field, this));
                }
            }
            leftScroller.addStyleName(SCROLLPANE_STYLE_NAME);
            leftScroller.add(leftList);
            add(leftScroller);
            add(moveButtonBar = new MoveButtonBar(this));

            ScrollPanel rightScroller = new ScrollPanel();
            rightScroller.setSize("150","300");
            rightList = new VerticalPanel();
            for(DisplayableFieldDTO field:lr.getSortedFields()) {
                rightList.add(new SortedField(field,this));
            }
            rightScroller.addStyleName(SCROLLPANE_STYLE_NAME);
            rightScroller.add(rightList);
            add(rightScroller);
            add(sortButtonBar = new SortButtonBar(this));
        }
        protected void addAll() {
            for(int i=leftList.getWidgetCount()-1;i>=0;i--) {
                SortableField sf = (SortableField)leftList.getWidget(i);
                DisplayableFieldDTO field = sf.getField();
                if(field.getSortOrder()==DisplayableFieldDTO.SORT_ORDER_NO_SORT) field.setSortOrder(DisplayableFieldDTO.SORT_ORDER_ASC);
                field.setSortPosition(rightList.getWidgetCount());
                rightList.add(new SortedField(field,this));
                leftList.remove(i);
            }
            leftSelectedCount = 0;
            moveButtonBar.getAddSelectedButton().setEnable(false);
        }
        protected void addSelected() {
            for(int i=leftList.getWidgetCount()-1;i>=0;i--) {
                SortableField sf = (SortableField)leftList.getWidget(i);
                if(sf.isSelected()) {
                    DisplayableFieldDTO field = sf.getField();
                    if(field.getSortOrder()==DisplayableFieldDTO.SORT_ORDER_NO_SORT) field.setSortOrder(DisplayableFieldDTO.SORT_ORDER_ASC);
                    field.setSortPosition(rightList.getWidgetCount());
                    rightList.add(new SortedField(field,this));
                    leftList.remove(i);
                }
            }
            leftSelectedCount = 0;
            moveButtonBar.getAddSelectedButton().setEnable(false);
        }
        protected void removeAll() {
            for(int i=rightList.getWidgetCount()-1;i>=0;i--) {
                SortedField sf = (SortedField)rightList.getWidget(i);
                DisplayableFieldDTO field = sf.getField();
                field.setSortOrder(DisplayableFieldDTO.SORT_ORDER_NO_SORT);
                field.setSortPosition(DisplayableFieldDTO.SORT_POSITION_NO_SORT);
                leftList.add(new SortableField(field, this));
                rightList.remove(i);
            }
            rightSelectedCount = 0;
            getSortButtonBar().getUpButton().setEnable(false);
            getSortButtonBar().getDownButton().setEnable(false);
        }
        protected void removeSelected() {
            for(int i=rightList.getWidgetCount()-1;i>=0;i--) {
                SortedField sf = (SortedField)rightList.getWidget(i);
                if(sf.isSelected()) {
                    DisplayableFieldDTO field = sf.getField();
                    field.setSortOrder(DisplayableFieldDTO.SORT_ORDER_NO_SORT);
                    field.setSortPosition(DisplayableFieldDTO.SORT_POSITION_NO_SORT);
                    leftList.add(new SortableField(field, this));
                    rightList.remove(i);
                }
            }
            rightSelectedCount = 0;
            getSortButtonBar().getUpButton().setEnable(false);
            getSortButtonBar().getDownButton().setEnable(false);
        }
        protected void notifyLeftListChanged(boolean selected) {
            if(selected) leftSelectedCount++;
            else leftSelectedCount--;
            moveButtonBar.getAddSelectedButton().setEnable(leftSelectedCount>0);
        }
        protected MoveButtonBar getMoveButtonBar() { return moveButtonBar; }
        protected SortButtonBar getSortButtonBar() { return sortButtonBar; }
        protected VerticalPanel getRightList() { return rightList; }
    }
    /**
     * The elements that are in the second tab (sortable fields), into the first list box
     */
    protected class SortableField extends Label {
        private static final String LBL_PRIMARY_STYLE_NAME = "selectable-listentry";
        private static final String LBL_SELECTED_STYLE = "selected";
        private DisplayableFieldDTO field;
        private boolean selected = false;
        private SortableFieldsPanel parent;
        public SortableField(DisplayableFieldDTO field,SortableFieldsPanel parent) {
            super();
            this.field=field;
            this.parent=parent;
            setText(field.getLibelle());
            selected = false;
            setStyleName(LBL_PRIMARY_STYLE_NAME);
            addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    selected = !selected;
                    if(selected) {
                        setStyleName(LBL_PRIMARY_STYLE_NAME+"-"+LBL_SELECTED_STYLE);
                    } else {
                        setStyleName(LBL_PRIMARY_STYLE_NAME);
                    }
                    SortableField.this.parent.notifyLeftListChanged(selected);
                }
            });
        }
        public DisplayableFieldDTO getField() { return field; }
        public boolean isSelected() { return selected; }
    }
    /**
     * The elements that are in the second tab (sortable fields), in the second listbox
     */
    protected class SortedField extends Grid {
        private DisplayableFieldDTO field;
        private SortableFieldsPanel parent;
        private boolean selected = false;
        private Label lbl;
        private ListBox lb;
        public SortedField(DisplayableFieldDTO field,SortableFieldsPanel parent) {
            super(1,2);
            getColumnFormatter().setWidth(0, "50%");
            getColumnFormatter().setWidth(1, "50%");
            this.field=field;
            this.parent=parent;
            lbl = new Label(field.getLibelle());
            lbl.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    selected = !selected;
                    notifySelectedChanged(selected);
                }
            });
            lbl.setStyleName(LBL_PRIMARY_STYLE_NAME);
            setWidget(0,0,lbl);
            lb = new ListBox(false);
            lb.setVisibleItemCount(1);
            lb.addItem("Ascendant", "ASC");
            lb.addItem("Descendant", "DESC");
            lb.setSelectedIndex(field.getSortOrder()==DisplayableFieldDTO.SORT_ORDER_ASC?0:1);
            lb.addChangeListener(new ChangeListener() {
                public void onChange(Widget sender) {
                    SortedField.this.field.setSortOrder(lb.getSelectedIndex()==0?DisplayableFieldDTO.SORT_ORDER_ASC:DisplayableFieldDTO.SORT_ORDER_DESC);
                }
            });
            setWidget(0,1,lb);
        }
        private void notifySelectedChanged(boolean selected) {
            if(selected) parent.rightSelectedCount++;
            else parent.rightSelectedCount--;
            if(selected) {
                lbl.setStyleName(LBL_PRIMARY_STYLE_NAME+"-"+LBL_SELECTED_STYLE);
            } else {
                lbl.setStyleName(LBL_PRIMARY_STYLE_NAME);
            }
            parent.getSortButtonBar().getUpButton().setEnable(parent.rightSelectedCount>0);
            parent.getSortButtonBar().getDownButton().setEnable(parent.rightSelectedCount>0);
            parent.getMoveButtonBar().pbRemoveSelected.setEnable(parent.rightSelectedCount>0);
        }
        public boolean isSelected() { return selected; }
        public DisplayableFieldDTO getField() { return field; }
    }

    protected class ButtonBar extends HorizontalPanel {
        private DlgSearchParams parent;
        public ButtonBar(DlgSearchParams parent) {
            super();
            this.parent=parent;
            Button btOk = new Button("Ok", new ClickListener() {

                public void onClick(Widget sender) {
                    ButtonBar.this.parent.okClicked();
                }
            });
            add(btOk);
            Button btCancel = new Button("Annuler", new ClickListener() {

                public void onClick(Widget sender) {
                    ButtonBar.this.parent.cancelClicked();
                }
            });
            add(btCancel);
        }
    }
    protected class MoveButtonBar extends VerticalPanel {
        private SortableFieldsPanel parent;
        private ImageButton pbAddAll;
        private ImageButton pbAddSelected;
        private ImageButton pbRemoveSelected;
        private ImageButton pbRemoveAll;
        public MoveButtonBar(SortableFieldsPanel parent) {
            super();
            this.parent=parent;
            pbAddAll = new ImageButton(GWTUtils.getContextPath()+"/img/bt-add-all.png","Tout ajouter");
            pbAddSelected = new ImageButton(GWTUtils.getContextPath()+"/img/bt-add-selected.png",GWTUtils.getContextPath()+"/img/bt-add-selected-deactivated.png",new HTML("Ajouter les s&eacute;l&eacute;ctionn&eacute;s").getHTML());
            pbAddSelected.setEnable(false);
            pbRemoveSelected = new ImageButton(GWTUtils.getContextPath()+"/img/bt-del-selected.png",GWTUtils.getContextPath()+"/img/bt-del-selected-deactivated.png",new HTML("Retirer les s&eacute;l&eacute;ctionn&eacute;s").getHTML());
            pbRemoveSelected.setEnable(false);
            pbRemoveAll = new ImageButton(GWTUtils.getContextPath()+"/img/bt-del-all.png","Tout retirer");

            pbAddAll.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    MoveButtonBar.this.parent.addAll();
                }
            });
            pbAddSelected.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    MoveButtonBar.this.parent.addSelected();
                }
            });
            pbRemoveSelected.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    MoveButtonBar.this.parent.removeSelected();
                }
            });
            pbRemoveAll.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    MoveButtonBar.this.parent.removeAll();
                }
            });
            add(pbAddAll);
            add(pbAddSelected);
            add(pbRemoveSelected);
            add(pbRemoveAll);
        }
        public ImageButton getAddSelectedButton() { return pbAddSelected; }
        public ImageButton getRemoveSelectedButton() { return pbRemoveSelected; }
    }
    protected class SortButtonBar extends VerticalPanel {
        private SortableFieldsPanel parent;
        private ImageButton btUp;
        private ImageButton btDown;
        public SortButtonBar(SortableFieldsPanel parent) {
            super();
            this.parent=parent;
            btUp = new ImageButton(GWTUtils.getContextPath()+"/img/bt_up.png", GWTUtils.getContextPath()+"/img/bt_up_deactivated.png", "Monter");
            btDown = new ImageButton(GWTUtils.getContextPath()+"/img/bt_down.png", GWTUtils.getContextPath()+"/img/bt_down_deactivated.png", "Descendre");
            btUp.setEnable(false); btDown.setEnable(false);
            btUp.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    _buttonUpPressed();
                }
            });
            btDown.addClickListener(new ClickListener() {
                public void onClick(Widget sender) {
                    _buttonDownPressed();
                }
            });
            add(btUp);
            add(btDown);
        }
        public ImageButton getUpButton() { return btUp; }
        public ImageButton getDownButton() { return btDown; }
        private void _buttonUpPressed() {
            VerticalPanel list = parent.getRightList();
            for(int i=1;i<list.getWidgetCount();i++) {
                Widget wd = list.getWidget(i);
                if(wd instanceof SortedField) {
                    SortedField sf = (SortedField)wd;
                    if(sf.isSelected()) {
                        list.remove(i);
                        list.insert(wd, i-1);
                        sf.getField().setSortPosition(i-1);
                    }
                }
            }
        }
        private void _buttonDownPressed() {
            VerticalPanel list = parent.getRightList();
            for(int i=list.getWidgetCount()-2;i>=0;i--) {
                Widget wd = list.getWidget(i);
                if(wd instanceof SortedField) {
                    SortedField sf = (SortedField)wd;
                    if(sf.isSelected()) {
                        list.remove(i);
                        list.insert(wd, i+1);
                        sf.getField().setSortPosition(i+1);
                    }
                }
            }
        }
    }
}
