/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */
package com.queplix.core.client.controls.grid;

import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.queplix.core.client.common.StringUtil;
import com.queplix.core.client.common.event.EventListener;
import com.queplix.core.client.common.ui.MenuPopup;
import com.queplix.core.client.common.ui.grid.DataGrid;
import com.queplix.core.client.common.ui.grid.DefaultGridView;
import com.queplix.core.client.common.ui.grid.GridSelectionModListener;
import com.queplix.core.client.common.ui.grid.GridSortListener;
import com.queplix.core.client.common.ui.grid.SelectionController;

import java.util.List;

/**
 * QGrid view implementation.
 *
 * @author Sergey Kozmin
 * @since 20 Oct 2006
 */
class QGridViewImpl extends QGridView implements QGridListener {
    private QGridModelImpl model;
    private boolean inPopup;

    private HorizontalPanel panel;
    private VerticalPanel vp;
    private Label spacer;
    private QGridPager pager;
    private DataGrid grid;

    public QGridViewImpl(QGridModelImpl model, boolean inPopup,
                         boolean customizable, boolean refreshable,
                         boolean hasExtendedSelectionActions,
                         boolean sendConfirmationEvent) {
        this.model = model;
        this.inPopup = inPopup;
        setupWidgets(customizable, refreshable, hasExtendedSelectionActions,
                sendConfirmationEvent);
        model.addPagerModelListener(this);
    }

    public void addPagerListener(QPagerListener listener) {
        pager.addPagerListener(listener);
    }

    public void removePagerListener(QPagerListener listener) {
        pager.removePagerListener(listener);
    }

    void addGridSortListener(GridSortListener listener) {
        grid.addGridSortListener(listener);
    }

    void addEventListener(EventListener listener) {
        grid.getEventSource().addEventListener(listener);
    }

    void addGridSelectionModListener(GridSelectionModListener listener) {
        pager.addGridSelectionModListener(listener);
    }

    public void clearSelection() {
        grid.getSelectionController().clearSelection();
    }

    public void selectRow(int row) {
        grid.getSelectionController().setRowType(row,
                SelectionController.SINGLE_SELECTED_ROW_TYPE);
    }

    public List getSelectedRows() {
        return grid.getSelectionController().getSelectedRows();
    }

    public void scrollGridToRow(int row) {
        grid.scrollGridToRow(row);
    }

    public void selectAll() {
        grid.getSelectionController().setRowsType(0,
                model.getData().getRecordsCount(),
                SelectionController.MULTIPLE_SELECTED_ROWS_TYPE);
    }

    public void invertSelection() {
        SelectionController controller = grid.getSelectionController();
        List selectedRows = controller.getSelectedRows(SelectionController
                .MULTIPLE_SELECTED_ROWS_TYPE);
        List notSelectedRows = controller.getSelectedRows(SelectionController
                .NOT_SELECTED_ROW_TYPE);

        controller.setRowsType(selectedRows,
                SelectionController.NOT_SELECTED_ROW_TYPE);

        controller.setRowsType(notSelectedRows,
                SelectionController.MULTIPLE_SELECTED_ROWS_TYPE);
    }

    private void setupWidgets(boolean customizable, boolean refreshable,
                              boolean hasExtendedSelectionActions,
                              boolean sendConfirmationEvent) {
        panel = new HorizontalPanel();
        vp = new VerticalPanel();
        spacer = new Label(" ");
        spacer.setStyleName("grid-Spacer");
        initWidget(panel);

        vp.addStyleName("grid-Container");

        pager = new QGridPager(model, inPopup, customizable, refreshable,
                hasExtendedSelectionActions);
        vp.add(pager);

        grid = new DataGrid(model.getGridModelImpl(), DefaultGridView.INSTANCE,
                inPopup, sendConfirmationEvent);
        vp.add(grid);

        panel.add(spacer);
        panel.add(vp);
    }

    public void pageDataIsChanged() {
        pager.reinitPager();
        clearSelection();
    }

    public void selectedRecordChanged(Long newSelectedRecordId) {
        Long selectedRecordId = model.getSelectedRecordId();
        if(selectedRecordId != null) {
            int index = model.getRowByRecordId(selectedRecordId);
            if(index >= 0) {
                selectRow(index);
            }
        }
    }

    public int getRowCount() {
        return grid.getRowCount();
    }

    public int getSelectedColumn() {
        return grid.getSelectedColumn();
    }

    public void setSelectedColumn(int column) {
        grid.setSelectedColumn(column);
    }


    // ======================== Resizable implementation =====================
    private int offsetHeight;
    private int offsetWidth;

    public void setOffsetHeight(int height) {
        if((height < 0) || (offsetHeight == height)) {
            return; // invalid or unchanged value
        }
        offsetHeight = height;
        if(isAttached()) {
            doSetOffsetHeight();
        }
    }

    public void setOffsetWidth(int width) {
        if((width < 0) || (offsetWidth == width)) {
            return; // invalid or unchanged value
        }
        offsetWidth = width;
        if(isAttached()) {
            doSetOffsetWidth();
        }
    }

    private void doSetOffsetHeight() {
        int pagerHeight = pager.getOffsetHeight();
        grid.setOffsetHeight(offsetHeight - pagerHeight);
        offsetHeight = grid.getOffsetHeight() + pagerHeight;
        String offsetHeightSize = StringUtil.pixelToSize(offsetHeight);
        panel.setHeight(offsetHeightSize);
        vp.setHeight(offsetHeightSize);
        spacer.setHeight(offsetHeightSize);
    }

    private void doSetOffsetWidth() {
        grid.setOffsetWidth(offsetWidth);
        offsetWidth = grid.getOffsetWidth();
        String offsetWidthSize = StringUtil.pixelToSize(offsetWidth);
        pager.setWidth(offsetWidthSize);
        panel.setWidth(offsetWidthSize);
        vp.setWidth(offsetWidthSize);
    }

    protected void onAttach() {
        super.onAttach();
        if(offsetHeight > 0) { // offsetHeight was set
            doSetOffsetHeight();
        }
        if(offsetWidth > 0) { // offsetWidth was set
            doSetOffsetWidth();
        }
    }

    public void setHeight(String height) {
        setOffsetHeight(StringUtil.sizeToPixel(height));
    }

    public void setWidth(String width) {
        setOffsetWidth(StringUtil.sizeToPixel(width));
    }
    // ===================== End of Resizable implementation ==================

    public MenuPopup getMenu() {
        return pager.getMenu();
    }
}
