/* This file is part of the KOffice project
 * Copyright (C) 2005 Thomas Zander <zander@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; version 2.

 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "KWStatisticsDialog.h"
#include "KWDocument.h"
#include "KWFrameSet.h"
#include <tdelocale.h>
#include <tqtabwidget.h>
#include <tqvbox.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqprogressdialog.h>
#include <tqcheckbox.h>

KWStatisticsDialog::KWStatisticsDialog( TQWidget *parent, KWDocument *document )
    : KDialogBase(parent, "statistics", true, i18n("Statistics"),KDialogBase::Ok, KDialogBase::Ok, false )
{
    TQWidget *page = new TQWidget( this );
    setMainWidget(page);
    TQVBoxLayout *topLayout = new TQVBoxLayout( page, 0, KDialog::spacingHint() );

    TQTabWidget *tab = new TQTabWidget( page );
    TQFrame *pageAll = 0;
    TQFrame *pageGeneral = 0;
    TQFrame *pageSelected = 0;
    for (int i=0; i < 7; ++i) {
        m_resultLabelAll[i] = 0;
        m_resultLabelSelected[i] = 0;
        if ( i < 6 )
            m_resultGeneralLabel[i]=0;
    }
    m_doc = document;
    m_parent = parent;
    m_canceled = true;


    // add Tab "General"
    pageGeneral = new TQFrame( this );
    tab->addTab( pageGeneral,  i18n( "General" ) );

    addBoxGeneral( pageGeneral, m_resultGeneralLabel );
    calcGeneral( m_resultGeneralLabel );

    // add Tab "All"
    pageAll = new TQFrame( this );
    tab->addTab( pageAll,  i18n( "Text" ) );

    addBox( pageAll, m_resultLabelAll, true );

    m_canceled = true;
    pageSelected = new TQFrame( this );
    tab->addTab( pageSelected,  i18n( "Selected Text" ) );
    // let's see if there's selected text
    bool b = docHasSelection();
    tab->setTabEnabled(pageSelected, b);
    if ( b ) {
        addBox( pageSelected, m_resultLabelSelected,  false);
        // assign results to 'selected' tab.
        if ( !calcStats( m_resultLabelSelected, true,true ) )
            return;
        if ( !calcStats( m_resultLabelAll, false,false ) )
            return;
        showPage( 2 );
    } else {
        // assign results
        if ( !calcStats( m_resultLabelAll, false, false ) )
            return;
        showPage( 1 );
    }
    topLayout->addWidget( tab );
    m_canceled = false;

}

void KWStatisticsDialog::slotRefreshValue(bool state)
{
    m_canceled = true;
    // let's see if there's selected text
    bool b = docHasSelection();
    if ( b )
    {
        if ( !calcStats( m_resultLabelSelected, true, true ) )
            return;
        if ( !calcStats( m_resultLabelAll, false, state ) )
            return;
    }
    else
    {
        // assign results
        if ( !calcStats( m_resultLabelAll, false, state ) )
            return;
    }
    m_canceled = false;
}

void KWStatisticsDialog::calcGeneral( TQLabel **resultLabel )
{
    TDELocale *locale = TDEGlobal::locale();

    resultLabel[0]->setText( locale->formatNumber( m_doc->pageCount(), 0) );
    int table =0;
    int picture = 0;
    int part = 0;
    int nbFrameset = 0;
    int nbFormula = 0;
    TQPtrListIterator<KWFrameSet> framesetIt( m_doc->framesetsIterator() );
    for ( framesetIt.toFirst(); framesetIt.current(); ++framesetIt ) {
        KWFrameSet *frameSet = framesetIt.current();
        if ( frameSet && frameSet->isVisible())
        {
            if ( frameSet->type() == FT_TABLE)
                table++;
            else if ( frameSet->type() == FT_PICTURE)
                picture++;
            else if ( frameSet->type() == FT_PART )
                part++;
            else if ( frameSet->type() == FT_FORMULA )
                nbFormula++;
            nbFrameset++;
        }
    }

    resultLabel[1]->setText( locale->formatNumber( nbFrameset, 0 ) );
    resultLabel[2]->setText( locale->formatNumber( picture, 0 ) );
    resultLabel[3]->setText( locale->formatNumber( table, 0 ) );
    resultLabel[4]->setText( locale->formatNumber( part, 0 ) );
    resultLabel[5]->setText( locale->formatNumber( nbFormula, 0 ) );
}

bool KWStatisticsDialog::calcStats( TQLabel **resultLabel, bool selection, bool useFootEndNote  )
{
    ulong charsWithSpace = 0L;
    ulong charsWithoutSpace = 0L;
    ulong words = 0L;
    ulong sentences = 0L;
    ulong lines = 0L;
    ulong syllables = 0L;

    // safety check result labels
    for (int i=0; i < 7; ++i) {
        if ( !resultLabel[i] ) {
            kdDebug() << "Warning: KWStatisticsDiaolog::calcStats result table not initialized." << endl;
            return false;
        }
    }

    // count paragraphs for progress dialog:
    ulong paragraphs = 0L;
    TQPtrListIterator<KWFrameSet> framesetIt( m_doc->framesetsIterator() );
    for ( framesetIt.toFirst(); framesetIt.current(); ++framesetIt ) {
        KWFrameSet *frameSet = framesetIt.current();
        if ( (frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE || frameSet->frameSetInfo() == KWFrameSet::FI_BODY) && frameSet->isVisible() )
        {
            if ( (useFootEndNote && frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE) ||
                    frameSet->frameSetInfo() == KWFrameSet::FI_BODY ) {
                paragraphs += frameSet->paragraphs();
            }
        }
    }
    TQProgressDialog progress( i18n( "Counting..." ), i18n( "Cancel" ), paragraphs, this, "count", true );
    progress.setMinimumDuration( 1000 );
    progress.setProgress( 0 );

    // do the actual counting
    for ( framesetIt.toFirst(); framesetIt.current(); ++framesetIt ) {
        KWFrameSet *frameSet = framesetIt.current();
        // Exclude headers and footers
        if ( (frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE || frameSet->frameSetInfo() == KWFrameSet::FI_BODY) && frameSet->isVisible() ) {
            if ( (useFootEndNote && frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE) || frameSet->frameSetInfo() == KWFrameSet::FI_BODY )
            {

                if( ! frameSet->statistics( &progress, charsWithSpace, charsWithoutSpace,
                                            words, sentences, syllables, lines, selection ) ) {
                    // someone pressed "Cancel"
                    return false;
                }
            }
        }
    }

    // assign results
    TDELocale *locale = TDEGlobal::locale();
    resultLabel[0]->setText( locale->formatNumber( charsWithSpace, 0) );
    resultLabel[1]->setText( locale->formatNumber( charsWithoutSpace, 0 ) );
    resultLabel[2]->setText( locale->formatNumber( syllables, 0 ) );
    resultLabel[3]->setText( locale->formatNumber( words, 0 ) );
    resultLabel[4]->setText( locale->formatNumber( sentences, 0 ) );
    resultLabel[5]->setText( locale->formatNumber( lines, 0 ) );
    // add flesch
    double f = calcFlesch( sentences, words, syllables );
    TQString flesch = locale->formatNumber( f , 1 );
    if( words < 200 ) {
        // a kind of warning if too few words:
        flesch = i18n("approximately %1").arg( flesch );
    }
    resultLabel[6]->setText( flesch );
    return true;
}

double KWStatisticsDialog::calcFlesch( ulong sentences, ulong words, ulong syllables )
{
    // calculate Flesch reading ease score:
    float flesch_score = 0;
    if( words > 0 && sentences > 0 )
        flesch_score = 206.835 - (1.015 * (words / sentences)) - (84.6 * syllables / words);
    return flesch_score;
}

void KWStatisticsDialog::addBoxGeneral( TQFrame *page, TQLabel **resultLabel )
{
    // Layout Managers
    TQVBoxLayout *topLayout = new TQVBoxLayout( page, 0, 7 );
    TQGroupBox *box = new TQGroupBox( i18n( "Statistics" ), page );
    TQGridLayout *grid = new TQGridLayout( box, 9, 3, KDialog::marginHint(), KDialog::spacingHint() );
    grid->setRowStretch (9, 1);
    // margins
    int fHeight = box->fontMetrics().height();
    grid->setMargin( fHeight );
    grid->addColSpacing( 1, fHeight );
    grid->addRowSpacing( 0, fHeight );

    // insert labels
    TQLabel *label1 = new TQLabel( i18n( "Number of pages:" ), box );
    grid->addWidget( label1, 1, 0, 1 );
    resultLabel[0] = new TQLabel( "", box );
    grid->addWidget( resultLabel[0], 1, 2, 2 );

    TQLabel *label2 = new TQLabel( i18n( "Number of frames:" ), box );
    grid->addWidget( label2, 2, 0, 1 );
    resultLabel[1] = new TQLabel( "", box );
    grid->addWidget( resultLabel[1], 2, 2, 2 );

    TQLabel *label3 = new TQLabel( i18n( "Number of pictures:" ), box );
    grid->addWidget( label3, 3, 0, 1 );
    resultLabel[2] = new TQLabel( "", box );
    grid->addWidget( resultLabel[2], 3, 2, 2 );


    TQLabel *label4 = new TQLabel( i18n( "Number of tables:" ), box );
    grid->addWidget( label4, 4, 0, 1 );
    resultLabel[3] = new TQLabel( "", box );
    grid->addWidget( resultLabel[3], 4, 2, 2 );

    TQLabel *label5 = new TQLabel( i18n( "Number of embedded objects:" ), box );
    grid->addWidget( label5, 5, 0, 1 );
    resultLabel[4] = new TQLabel( "", box );
    grid->addWidget( resultLabel[4], 5, 2, 2 );

    TQLabel *label6 = new TQLabel( i18n( "Number of formula frameset:" ), box );
    grid->addWidget( label6, 6, 0, 1 );
    resultLabel[5] = new TQLabel( "", box );
    grid->addWidget( resultLabel[5], 6, 2, 2 );

    topLayout->addWidget( box );
}

void KWStatisticsDialog::addBox( TQFrame *page, TQLabel **resultLabel, bool calcWithFootNoteCheckbox )
{
    // Layout Managers
    TQVBoxLayout *topLayout = new TQVBoxLayout( page, 0, 7 );
    if ( calcWithFootNoteCheckbox )
    {
        TQWidget *w = new TQWidget(page);
        topLayout->addWidget( w );
        TQVBoxLayout *noteLayout = new TQVBoxLayout( w, KDialog::marginHint(), 0 );
        TQCheckBox *calcWithFootNote = new TQCheckBox( i18n("&Include text from foot- and endnotes"), w);
        noteLayout->addWidget( calcWithFootNote );
        connect( calcWithFootNote, TQ_SIGNAL(toggled ( bool )), this, TQ_SLOT( slotRefreshValue(bool)));
    }


    TQGroupBox *box = new TQGroupBox( i18n( "Statistics" ), page );
    TQGridLayout *grid = new TQGridLayout( box, 9, 3, KDialog::marginHint(), KDialog::spacingHint() );
    grid->setRowStretch (9, 1);

    // margins
    int fHeight = box->fontMetrics().height();
    grid->setMargin( fHeight );
    grid->addColSpacing( 1, fHeight );
    grid->addRowSpacing( 0, fHeight );

    //maximum size for result column (don't know how to do this better..)
    TQString init = i18n("approximately %1").arg( "00000000" );

    // insert labels
    TQLabel *label1 = new TQLabel( i18n( "Characters including spaces:" ), box );
    grid->addWidget( label1, 1, 0, 1 );
    resultLabel[0] = new TQLabel( "", box );
    grid->addWidget( resultLabel[0], 1, 2, 2 );

    TQLabel *label2 = new TQLabel( i18n( "Characters without spaces:" ), box );
    grid->addWidget( label2, 2, 0, 1 );
    resultLabel[1] = new TQLabel( "", box );
    grid->addWidget( resultLabel[1], 2, 2, 2 );

    TQLabel *label3 = new TQLabel( i18n( "Syllables:" ), box );
    grid->addWidget( label3, 3, 0, 1 );
    resultLabel[2] = new TQLabel( "", box );
    grid->addWidget( resultLabel[2], 3, 2, 2 );

    TQLabel *label4 = new TQLabel( i18n( "Words:" ), box );
    grid->addWidget( label4, 4, 0, 1 );
    resultLabel[3] = new TQLabel( "", box );
    grid->addWidget( resultLabel[3], 4, 2, 2 );

    TQLabel *label5 = new TQLabel( i18n( "Sentences:" ), box );
    grid->addWidget( label5, 5, 0, 1 );
    resultLabel[4] = new TQLabel( "", box );
    grid->addWidget( resultLabel[4], 5, 2, 2 );

    TQLabel *label6 = new TQLabel( i18n( "Lines:" ), box );
    grid->addWidget( label6, 6, 0, 1 );
    resultLabel[5] = new TQLabel( "", box );
    grid->addWidget( resultLabel[5], 6, 2, 2 );


    TQLabel *label7 = new TQLabel( i18n( "Flesch reading ease:" ), box );
    grid->addWidget( label7, 7, 0, 1 );
    resultLabel[6] = new TQLabel( init, box );
    grid->addWidget( resultLabel[6], 7, 2, 2 );

    topLayout->addWidget( box );
}

bool KWStatisticsDialog::docHasSelection()const
{
    TQPtrListIterator<KWFrameSet> fsIt( m_doc->framesetsIterator() );

    for ( ; fsIt.current(); ++fsIt ) {
        KWFrameSet *fs = fsIt.current();
        if ( fs->paragraphsSelected() ) {
            return true;
        }
    }
    return false;
}

#include "KWStatisticsDialog.moc"

