/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
package com.sun.star.wizards.ui;

import java.util.Vector;
import com.sun.star.wizards.common.*;
import com.sun.star.wizards.db.*;
import com.sun.star.lang.EventObject;
//import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.beans.*;
import com.sun.star.sdbc.SQLException;
import com.sun.star.uno.AnyConverter;

import com.sun.star.awt.*;

public class AggregateComponent extends ControlScroller
{

    String[] sFunctions;
    String[] sFunctionOperators = new String[]
    {
        "SUM", "AVG", "MIN", "MAX"
    };
    ;
    QueryMetaData CurDBMetaData;
    XButton optDetailQuery;
    XButton optSummaryQuery;
    String soptDetailQuery;
    String soptSummaryQuery;
    String slblAggregate;
    String slblFieldNames;
    String sDuplicateAggregateFunction;
    int Count;
    int iQueryType;
    final int SOADDROW = 1;
    final int SOREMOVEROW = 2;
    final int CONTROLROWDIST = 18;
    Vector ControlRowVector;
    String OPTIONBUTTONDETAILQUERY_ITEM_CHANGED = "toggleComponent";
    String OPTIONBUTTONSUMMARYQUERY_ITEM_CHANGED = "toggleComponent";
    String LISTBOXFUNCTIONS_ACTION_PERFORMED;
    String LISTBOXFUNCTIONS_ITEM_CHANGED;
    String LISTBOXFIELDNAMES_ACTION_PERFORMED;
    String LISTBOXFIELDNAMES_ITEM_CHANGED;
    String COMMANDBUTTONPLUS_ACTION_PERFORMED = "addRow";
    String COMMANDBUTTONMINUS_ACTION_PERFORMED = "removeRow";
    Vector ControlRows;
    int curHelpID;
    int lastHelpIndex;

    /** Creates a new instance of AggrgateComponent */
    public AggregateComponent(WizardDialog _CurUnoDialog, QueryMetaData _CurDBMetaData, int _iStep, int _iPosX, int _iPosY, int _iWidth, int _uitextfieldcount, int _firstHelpID)
    {
        super(_CurUnoDialog, _CurDBMetaData.xMSF, _iStep, _iPosX + 10, _iPosY, _iWidth - 12, _uitextfieldcount, 18, _firstHelpID + 2);
        try
        {
            curHelpID = _firstHelpID;
            this.CurDBMetaData = _CurDBMetaData;
            ;
            Count = 1;
            optDetailQuery = CurUnoDialog.insertRadioButton("optDetailQuery", 0, new ActionListenerImpl(),
                    new String[]
                    {
                        "Height", "HelpURL", "Label", "PositionX", "PositionY", "State", "Step", "TabIndex", "Width"
                    },
                    new Object[]
                    {
                        new Integer(8), "HID:" + curHelpID, soptDetailQuery, new Integer(_iPosX), new Integer(iCompPosY - 42), new Short((short) 1), IStep, new Short(curtabindex++), new Integer(iCompWidth)
                    });

            optSummaryQuery = CurUnoDialog.insertRadioButton("optSummaryQuery", 0, new ActionListenerImpl(),
                    new String[]
                    {
                        "Height", "HelpURL", "Label", "MultiLine", "PositionX", "PositionY", "Step", "TabIndex", "Width"
                    },
                    new Object[]
                    {
                        new Integer(16), "HID:" + (curHelpID + 1), soptSummaryQuery, Boolean.TRUE, new Integer(_iPosX), new Integer(iCompPosY - 32), IStep, new Short(curtabindex++), new Integer(iCompWidth)
                    });
            CurUnoDialog.insertLabel("lblAggregate",
                    new String[]
                    {
                        "Height", "Label", "PositionX", "PositionY", "Step", "TabIndex", "Width"
                    },
                    new Object[]
                    {
                        new Integer(8), slblAggregate, new Integer(iCompPosX + 5), new Integer(iCompPosY - 10), IStep, new Short(curtabindex++), new Integer(90)
                    });
            CurUnoDialog.insertLabel("lblFieldnames",
                    new String[]
                    {
                        "Height", "Label", "PositionX", "PositionY", "Step", "TabIndex", "Width"
                    },
                    new Object[]
                    {
                        new Integer(8), slblFieldNames, new Integer(iCompPosX + 101), new Integer(iCompPosY - 10), IStep, new Short(curtabindex++), new Integer(90)
                    });
            this.setTotalFieldCount(1);
            FontDescriptor oFontDescriptor = new FontDescriptor();
            oFontDescriptor.Weight = com.sun.star.awt.FontWeight.BOLD;
            oFontDescriptor.Height = (short) 14;

            int iButtonPosY = iCompPosY + iCompHeight + 3;
            CurUnoDialog.insertButton("btnplus", SOADDROW, new ActionListenerImpl(),
                    new String[]
                    {
                        "FontDescriptor", "Height", "HelpURL", "Label", "PositionX", "PositionY", "Step", "TabIndex", "Width"
                    },
                    new Object[]
                    {
                        oFontDescriptor, new Integer(14), "HID:" + (lastHelpIndex + 1), "+", new Integer(_iPosX + iCompWidth - 36), new Integer(iButtonPosY), IStep, new Short((curtabindex++)), new Integer(16)
                    });
            CurUnoDialog.insertButton("btnminus", SOREMOVEROW, new ActionListenerImpl(),
                    new String[]
                    {
                        "FontDescriptor", "Height", "HelpURL", "Label", "PositionX", "PositionY", "Step", "TabIndex", "Width"
                    },
                    new Object[]
                    {
                        oFontDescriptor, new Integer(14), "HID:" + (lastHelpIndex + 2), "-", new Integer(_iPosX + iCompWidth - 16), new Integer(iButtonPosY), IStep, new Short(curtabindex++), new Integer(16)
                    });
            CurDBMetaData.Type = getQueryType();
        }
        catch (com.sun.star.uno.Exception exception)
        {
            Resource.showCommonResourceError(CurDBMetaData.xMSF);
        }
    }

    public int getQueryType()
    {
        if (((Short) CurUnoDialog.getControlProperty("optDetailQuery", "State")).intValue() == 1)
        {
            return QueryMetaData.QueryType.SODETAILQUERY;
        }
        else
        {
            return QueryMetaData.QueryType.SOSUMMARYQUERY;
        }
    }

    class ActionListenerImpl implements com.sun.star.awt.XActionListener
    {

        public void disposing(EventObject eventObject)
        {
        }

        public void actionPerformed(com.sun.star.awt.ActionEvent actionEvent)
        {
            try
            {
                int iKey = CurUnoDialog.getControlKey(actionEvent.Source, CurUnoDialog.ControlList);
                switch (iKey)
                {
                    case SOADDROW:
                        addRow();
                        break;

                    case SOREMOVEROW:
                        removeRow();
                        break;

                    default:
                        toggleComponent();
                        break;
                }
            }
            catch (Exception exception)
            {
                exception.printStackTrace(System.out);
            }
        }
    }

    public int getCount()
    {
        return Count;
    }

    protected void insertControlGroup(int i, int ypos)
    {
        if (i == 0)
        {
            int BaseID = 2300;
            soptDetailQuery = CurUnoDialog.m_oResource.getResText(BaseID + 11);
            soptSummaryQuery = CurUnoDialog.m_oResource.getResText(BaseID + 12);
            slblAggregate = CurUnoDialog.m_oResource.getResText(BaseID + 16);
            slblFieldNames = CurUnoDialog.m_oResource.getResText(BaseID + 17);
            sFunctions = CurUnoDialog.m_oResource.getResArray(BaseID + 40, 4);

            sDuplicateAggregateFunction = CurUnoDialog.m_oResource.getResText(BaseID + 90);
        }
        if (ControlRowVector == null)
        {
            ControlRowVector = new Vector();
        }
        int locHelpID = curHelpIndex + (i * 2);
        ControlRow oControlRow = new ControlRow(i, ypos, locHelpID);
        ControlRowVector.add(oControlRow);
    }

    protected void setControlGroupVisible(int _index, boolean _bIsVisible)
    {
        ControlRow oControlRow = (ControlRow) ControlRowVector.elementAt(_index);
        oControlRow.setVisible(_bIsVisible);
        if (_index >= (this.CurDBMetaData.AggregateFieldNames.length))
        {
            oControlRow.settovoid();
        }
    }

    protected void addRow()
    {
        int fieldcount = super.getTotalFieldCount();
        registerControlGroupAtIndex(fieldcount);
        if (fieldcount < super.getBlockIncrementation())
        {
            ControlRow oControlRow = (ControlRow) ControlRowVector.elementAt(fieldcount);
            oControlRow.setVisible(true);
            oControlRow.settovoid();
        }
        else
        {
            ControlRow oControlRow = (ControlRow) ControlRowVector.elementAt(super.getBlockIncrementation() - 1);
            super.setScrollValue(getScrollValue() + 1, (fieldcount + 1));
            oControlRow.settovoid();
        }
        fieldcount++;
        super.setTotalFieldCount(fieldcount);
        toggleButtons();
        CurUnoDialog.repaintDialogStep();
    }

    protected void removeRow()
    {
        int fieldcount = super.getTotalFieldCount();
        if (fieldcount > 0)
        {
            ControlRow oControlRow;
            fieldcount--;
            if ((fieldcount + 1) <= super.getBlockIncrementation())
            {
                oControlRow = (ControlRow) ControlRowVector.elementAt(fieldcount);
                oControlRow.setVisible(false);
            }
            super.setScrollValue(getScrollValue() - 1, (fieldcount));
            super.unregisterControlGroup(fieldcount);

        }
        toggleButtons();
        CurUnoDialog.repaintDialogStep();
    }

    protected void toggleButtons()
    {
        ControlRow curcontrolrow = null;
        boolean biscomplete = true;
        CurDBMetaData.Type = getQueryType();
        CurUnoDialog.setControlProperty("btnminus", "Enabled", new Boolean((super.getTotalFieldCount() > 0) && (CurDBMetaData.Type == QueryMetaData.QueryType.SOSUMMARYQUERY)));
        int fieldcount = super.getCurFieldCount();
        if (fieldcount > 0)
        {
            curcontrolrow = (ControlRow) ControlRowVector.elementAt(super.getCurFieldCount() - 1);
            biscomplete = curcontrolrow.isComplete();
        }
        CurUnoDialog.setControlProperty("btnplus", "Enabled", new Boolean(biscomplete && (CurDBMetaData.Type == QueryMetaData.QueryType.SOSUMMARYQUERY)));
        togglefollowingDialogSteps();
    }

    public void toggleComponent()
    {
        CurDBMetaData.Type = getQueryType();
        boolean benableComponent = isAggregateComponentEnabled();
        CurUnoDialog.setControlProperty("lblAggregate", "Enabled", new Boolean(benableComponent));
        CurUnoDialog.setControlProperty("lblFieldnames", "Enabled", new Boolean(benableComponent));
        toggleButtons();
        super.toggleComponent(benableComponent);
        super.toggleControls(benableComponent);
        togglefollowingDialogSteps();
    }

    private boolean isAggregateComponentEnabled()
    {
        return (CurDBMetaData.Type == QueryMetaData.QueryType.SOSUMMARYQUERY);
    }

    public boolean isGroupingpossible()
    {
        try
        {
            boolean benableGroupPage = isAggregateComponentEnabled() && CurDBMetaData.xDBMetaData.supportsGroupBy() && hasonlycompletefunctions();
            String[][] sAggregateFieldNames = this.getAggregateFieldNames();
            if (benableGroupPage)
            {
                for (int i = 0; i < CurDBMetaData.NumericFieldNames.length; i++)
                {
                    boolean bisthere = (JavaTools.FieldInTable(sAggregateFieldNames, CurDBMetaData.NumericFieldNames[i]) > -1);
                    if (!bisthere)
                    {
                        return true;
                    }
                }
            }
        }
        catch (SQLException e)
        {
            e.printStackTrace(System.out);
        }
        return false;
    }

    private void togglefollowingDialogSteps()
    {
        boolean benabletherest = true;
        boolean benableGroupPage = isGroupingpossible();
        CurUnoDialog.setStepEnabled(UIConsts.SOGROUPSELECTIONPAGE, benableGroupPage);
        CurUnoDialog.setStepEnabled(UIConsts.SOGROUPFILTERPAGE, benableGroupPage && CurDBMetaData.GroupFieldNames.length > 0);
        if (isAggregateComponentEnabled())
        {
            benabletherest = hasonlycompletefunctions();
        }
        CurUnoDialog.enablefromStep(UIConsts.SOTITLESPAGE, benabletherest);
        CurUnoDialog.enableNextButton(benabletherest);
    }

    private void hideControlRowsfromindex(int _index)
    {
        if (_index < this.ControlRowVector.size())
        {
            for (int i = _index; i < ControlRowVector.size(); i++)
            {
                ControlRow oControlRow = (ControlRow) ControlRowVector.elementAt(i);
//              if (i == _index)
//                  oControlRow.settovoid();
//              else
                oControlRow.setVisible(false);
            }
        }

    }

    public String[][] getAggregateFieldNames()
    {
        try
        {
            CurDBMetaData.Type = getQueryType();
            if (CurDBMetaData.Type == QueryMetaData.QueryType.SOSUMMARYQUERY)
            {
                Vector aggregatevector = new Vector();
                PropertyValue[][] aggregatelist = this.getScrollFieldValues();
                PropertyValue[] currowproperties;
                PropertyValue curaggregateproperty;
                int a = 0;
                if (CurDBMetaData.AggregateFieldNames != null)
                {
                    for (int i = 0; i < aggregatelist.length; i++)
                    {
                        currowproperties = aggregatelist[i];
                        if ((currowproperties[0].Value != null) && (currowproperties[1].Value != null))
                        {
                            short[] iselfield = (short[]) AnyConverter.toArray(currowproperties[1].Value);
                            short[] iselfunction = (short[]) AnyConverter.toArray(currowproperties[0].Value);
                            if ((iselfield.length > 0) && (iselfunction.length > 0))
                            {
                                String[] curaggregatename = new String[2];
                                curaggregatename[0] = CurDBMetaData.NumericFieldNames[iselfield[0]];
                                curaggregatename[1] = this.sFunctionOperators[iselfunction[0]];
                                aggregatevector.add(curaggregatename);
                                a++;
                            }
                        }
                    }
                }
                CurDBMetaData.AggregateFieldNames = new String[a][2];
                aggregatevector.toArray(CurDBMetaData.AggregateFieldNames);
            }

            int iduplicate = JavaTools.getDuplicateFieldIndex(CurDBMetaData.AggregateFieldNames);
            if (iduplicate != -1)
            {
                sDuplicateAggregateFunction = JavaTools.replaceSubString(sDuplicateAggregateFunction, CurDBMetaData.AggregateFieldNames[iduplicate][0], "<NUMERICFIELD>");
                int index = JavaTools.FieldInList(sFunctionOperators, CurDBMetaData.AggregateFieldNames[iduplicate][1]);
                String sDisplayFunction = sFunctions[index];
                sDuplicateAggregateFunction = JavaTools.replaceSubString(sDuplicateAggregateFunction, sDisplayFunction, "<FUNCTION>");
                CurUnoDialog.showMessageBox("WarningBox", VclWindowPeerAttribute.OK, sDuplicateAggregateFunction);
                CurUnoDialog.vetoableChange(new java.beans.PropertyChangeEvent(CurUnoDialog, "Steps", new Integer(1), new Integer(2)));
                return new String[][]
                        {
                        };
            }
            else
            {
                return CurDBMetaData.AggregateFieldNames;
            }
        }
        catch (Exception exception)
        {
            exception.printStackTrace(System.out);
            return null;
        }
    }

    public void initialize()
    {
        CurDBMetaData.setNumericFields();
        initializeScrollFields();
        int icount = CurDBMetaData.AggregateFieldNames.length;
        if (icount == 0)
        {
            super.initialize(1);
            hideControlRowsfromindex(1);
        }
        else
        {
            super.initialize(icount);
            hideControlRowsfromindex(icount);
        }
        toggleComponent();
        CurUnoDialog.repaintDialogStep();
    }

    protected void initializeScrollFields()
    {
        ControlRow curControlRow;
        if (CurDBMetaData.AggregateFieldNames != null)
        {
            for (int i = 0; i < this.getBlockIncrementation(); i++)
            {
                curControlRow = (ControlRow) ControlRowVector.elementAt(i);
                curControlRow.insertFieldNames();
            }
            for (int i = 0; i <= CurDBMetaData.AggregateFieldNames.length; i++)
            {
                registerControlGroupAtIndex(i);
            }
        }
    }

    private void registerControlGroupAtIndex(int _index)
    {
        short[] iselfunctionlist = new short[]
        {
        };
        short[] iselfieldslist = new short[]
        {
        };
        PropertyValue[] currowproperties = new PropertyValue[2];
        if (_index < CurDBMetaData.AggregateFieldNames.length)
        {
            short iselfieldsindex = (short) JavaTools.FieldInList(CurDBMetaData.NumericFieldNames, CurDBMetaData.AggregateFieldNames[_index][0]);
            iselfieldslist = new short[]
                    {
                        iselfieldsindex
                    };
            short iselfunctionindex = (short) JavaTools.FieldInList(sFunctionOperators, CurDBMetaData.AggregateFieldNames[_index][1]);
            iselfunctionlist = new short[]
                    {
                        iselfunctionindex
                    };
        }
        currowproperties[0] = Properties.createProperty(getFunctionControlName(_index), iselfunctionlist, _index);
        currowproperties[1] = Properties.createProperty(getFieldsControlName(_index), iselfieldslist, _index);     //getTitleName(i)
        super.registerControlGroup(currowproperties, _index);
    }

    private String getFunctionControlName(int _index)
    {
        String namesuffix = "_" + String.valueOf(_index + 1);
        return "lstfunctions" + namesuffix;
    }

    private String getFieldsControlName(int _index)
    {
        String namesuffix = "_" + String.valueOf(_index + 1);
        return "lstFieldnames" + namesuffix;
    }

    private boolean hasonlycompletefunctions()
    {
        int maxfieldcount = super.getCurFieldCount();
        if (maxfieldcount > 0)
        {
            ControlRow curcontrolrow = (ControlRow) this.ControlRowVector.elementAt(maxfieldcount - 1);
            return curcontrolrow.isComplete();
        }
        else
        {
            return false;
        }
    }

    protected class ControlRow
    {

        private XListBox xFieldListBox;
        private XListBox xFunctionListBox;
        private int index;

        protected ControlRow(int _index, int ypos, int _curHelpID)
        {
            try
            {
                this.index = _index;
                xFunctionListBox = CurUnoDialog.insertListBox(getFunctionControlName(index), 1, null, new ItemListenerImpl(),
                        new String[]
                        {
                            "Dropdown", "Height", "HelpURL", "PositionX", "PositionY", "Step", "StringItemList", "TabIndex", "Width"
                        },
                        new Object[]
                        {
                            Boolean.TRUE, new Integer(12), "HID:" + _curHelpID++, new Integer(iCompPosX + 4), new Integer(ypos), UIConsts.INVISIBLESTEP, sFunctions, new Short(curtabindex++), new Integer(88)
                        });

                xFieldListBox = CurUnoDialog.insertListBox(getFieldsControlName(index), 1, null, new ItemListenerImpl(),
                        new String[]
                        {
                            "Dropdown", "Height", "HelpURL", "PositionX", "PositionY", "Step", "TabIndex", "Width"
                        },
                        new Object[]
                        {
                            Boolean.TRUE, new Integer(12), "HID:" + _curHelpID++, new Integer(iCompPosX + 98), new Integer(ypos), UIConsts.INVISIBLESTEP, new Short(curtabindex++), new Integer(86)
                        });
                lastHelpIndex = _curHelpID - 1;
            }
            catch (Exception exception)
            {
                exception.printStackTrace(System.out);
            }
        }

        private String getSelectedFieldName()
        {
            return xFieldListBox.getSelectedItem();
        }

        private String getSelectedFunction()
        {
            return xFunctionListBox.getSelectedItem();
        }

        private void setVisible(boolean _bvisible)
        {
            CurUnoDialog.setControlVisible(getFunctionControlName(index), _bvisible);
            CurUnoDialog.setControlVisible(getFieldsControlName(index), _bvisible);
        }

        private void insertFieldNames()
        {
            Helper.setUnoPropertyValue(UnoDialog.getModel(xFieldListBox), "StringItemList", CurDBMetaData.NumericFieldNames);
        }

        private boolean isComplete()
        {
            boolean bfieldnameisselected = (Helper.getUnoArrayPropertyValue(UnoDialog.getModel(xFieldListBox), "SelectedItems") != null);
            boolean bfunctionisselected = (Helper.getUnoArrayPropertyValue(UnoDialog.getModel(xFunctionListBox), "SelectedItems") != null);
            return (bfieldnameisselected && bfunctionisselected);
        }

        private void settovoid()
        {
            CurUnoDialog.deselectListBox(xFieldListBox);
            CurUnoDialog.deselectListBox(xFunctionListBox);
        }

        protected class ItemListenerImpl implements com.sun.star.awt.XItemListener
        {

            public void itemStateChanged(com.sun.star.awt.ItemEvent EventObject)
            {
                try
                {
                    toggleButtons();
                    togglefollowingDialogSteps();
                }
                catch (Exception exception)
                {
                    exception.printStackTrace(System.out);
                }
            }

            public void disposing(com.sun.star.lang.EventObject eventObject)
            {
            }
        }
    }
}
