/*
    This file is part of KOrganizer.
    Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>

    This program 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.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include <qpopupmenu.h>
#include <qfont.h>
#include <qfontmetrics.h>
#include <qkeycode.h>
#include <qhbox.h>
#include <qvbox.h>
#include <qpushbutton.h>
#include <qtooltip.h>
#include <qpainter.h>
#include <qwhatsthis.h>
#ifndef DESKTOP_VERSION
#include <qpe/qpeapplication.h>
#else
#include <qapplication.h>
#endif

#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kiconloader.h>

#include <kcalendarsystem.h>

#ifndef KORG_NOPRINTER
#include "calprinter.h"
#endif
#include "koprefs.h"
#ifndef KORG_NOPLUGINS
#include "kocore.h"
#endif
#include "koglobals.h"
#include <libkcal/kincidenceformatter.h>

#include "komonthview.h"

#define PIXMAP_SIZE 5

class KNOWhatsThis :public QWhatsThis
{
public:
    KNOWhatsThis( KNoScrollListBox* sbox ) : QWhatsThis( sbox ), _wid( sbox) { };

protected:
  virtual QString text( const QPoint& p)
  {
    return _wid->getWhatsThisText(p) ;
  };
private:
    KNoScrollListBox* _wid;
  
};


KNoScrollListBox::KNoScrollListBox(QWidget *parent,const char *name)
  : QListBox(parent, name)
{
#ifndef DESKTOP_VERSION
    QPEApplication::setStylusOperation( viewport(), QPEApplication::RightOnHold );
#endif 
    new KNOWhatsThis(this);
}

QString KNoScrollListBox::getWhatsThisText(QPoint p) 
{
    QListBoxItem* item = itemAt ( p );
    if ( ! item ) {
        return i18n("Click in the cell or\non the date label\nto add an event!");
    }
    return KIncidenceFormatter::instance()->getFormattedText(((MonthViewItem*) item)->incidence());
}
void KNoScrollListBox::keyPressEvent(QKeyEvent *e)
{
 
  switch(e->key()) {
    case Key_Right:
        // if ( e->state() == Qt::ControlButton )
        {
            e->ignore();
            return;
        }
        scrollBy(4,0);
      break;
    case Key_Left:
        //  if ( e->state() == Qt::ControlButton )
            {
            e->ignore();
            return;
        }
      scrollBy(-4,0);
      break;
    case Key_Up:
      if(!count()) break;
      setCurrentItem((currentItem()+count()-1)%count());
      if(!itemVisible(currentItem())) {
        if((unsigned int) currentItem() == (count()-1)) {
          setTopItem(currentItem()-numItemsVisible()+1);
        } else {
          setTopItem(topItem()-1);
        }
      }
      break;
    case Key_Down:
      if(!count()) break;
      setCurrentItem((currentItem()+1)%count());
      if(!itemVisible(currentItem())) {
        if(currentItem() == 0) {
          setTopItem(0);
        } else {
          setTopItem(topItem()+1);
        }
      }
      break;
    case Key_Shift:
      emit shiftDown();
      break;
    default:
        e->ignore();
      break;
  }
}

void KNoScrollListBox::keyReleaseEvent(QKeyEvent *e)
{
  switch(e->key()) {
    case Key_Shift:
      emit shiftUp();
      break;
    default:
      break;
  }
}

void KNoScrollListBox::mousePressEvent(QMouseEvent *e)
{
  QListBox::mousePressEvent(e);

  if(e->button() == RightButton) {
    emit rightClick();
  }
}

MonthViewItem::MonthViewItem( Incidence *incidence, QDate qd, const QString & s)
  : QListBoxItem()
{
  setText( s );

  mIncidence = incidence;
  mDate = qd;
  // QWhatsThis::add(this,KIncidenceFormatter::instance()->getFormattedText( mIncidence  ));
  mRecur = false;
  mAlarm = false;
  mReply = false;
  mInfo = false;
}

void MonthViewItem::paint(QPainter *p)
{
#if QT_VERSION >= 0x030000
  bool sel = isSelected();
#else
  bool sel = selected();
#endif 


  if (KOPrefs::instance()->mMonthViewUsesCategoryColor)
  {
    p->setBackgroundColor( palette().color( QPalette::Normal,  \
	    sel ? QColorGroup::Highlight : QColorGroup::Background ) );
    p->eraseRect( 0, 0, listBox()->maxItemWidth(), height( listBox() ) );
  }
  int x = 1;
  int y = 3;//(height() - mRecurPixmap.height()) /2; 
  int size = PIXMAP_SIZE;
  if ( QApplication::desktop()->width() < 300 )
       size = 3;
  if ( KOPrefs::instance()->mMonthShowIcons ) {
      if ( mInfo ) { 
          p->fillRect ( x, y,size,size, Qt::darkGreen );
          x += size + 1;
      }
      if ( mRecur ) {
          p->fillRect ( x, y,size,size, Qt::blue );
          x += size + 1;
      }
      if ( mAlarm ) {
          p->fillRect ( x, y,size,size, Qt::red );
          x += size + 1;
      }
      if ( mReply ) {
          p->fillRect ( x, y,size,size, Qt::yellow );
          x += size + 1;
      }
  }
  QFontMetrics fm = p->fontMetrics();
  int yPos;
  int pmheight = size;
  if( pmheight < fm.height() )
    yPos = fm.ascent() + fm.leading()/2;
  else
    yPos = pmheight/2 - fm.height()/2  + fm.ascent();
  p->setPen( palette().color( QPalette::Normal, sel ? \
	  QColorGroup::HighlightedText : QColorGroup::Foreground ) );
  p->drawText( x, yPos, text() );
  if ( mIncidence->cancelled() ) {
      int wid = fm.width( text() );
      p->drawLine( x, yPos- fm.height()/2+2,x+wid, yPos- fm.height()/2 +2);
  }
      
}

int MonthViewItem::height(const QListBox *lb) const
{
  return  lb->fontMetrics().lineSpacing()+1;
}

int MonthViewItem::width(const QListBox *lb) const
{ 
    int size = PIXMAP_SIZE;
  if ( QApplication::desktop()->width() < 300 )
       size = 3;
  int x = 1; 
  if ( mInfo ) {
    x += size + 1;
  }
  if( mRecur ) {
    x += size+1;
  }
  if( mAlarm ) {
    x += size+1;
  }
  if( mReply ) {
    x += size+1;
  }

  return( x + lb->fontMetrics().width( text() ) + 1 );
}


MonthViewCell::MonthViewCell( KOMonthView *parent)
  : QWidget( parent ),
    mMonthView( parent )
{

  QVBoxLayout *topLayout = new QVBoxLayout( this );

  // mLabel = new QLabel( this );QPushButton 
  mLabel = new QPushButton( this );
  //mLabel->setFrameStyle( QFrame::Panel | QFrame::Plain );
  //mLabel->setLineWidth( 1 );
  //mLabel->setAlignment( AlignCenter );
  mLabel->setFlat( true );
  mItemList = new KNoScrollListBox( this );
  mItemList->setMinimumSize( 10, 10 );
  mItemList->setFrameStyle( QFrame::Panel | QFrame::Plain );
  mItemList->setLineWidth( 1 );
  topLayout->addWidget( mItemList );
  mLabel->raise();
  // QColor( 0,0,255 )    QColor( 160,1600,255 )
  mStandardPalette = palette();
  mStandardPalette.setColor(QColorGroup::Base, mStandardPalette.color( QPalette::Normal, QColorGroup::Background ) );

  enableScrollBars( false );
  updateConfig();
  connect( mLabel, SIGNAL( clicked( )),
           SLOT( newEvent() ));
  connect( mItemList, SIGNAL( doubleClicked( QListBoxItem *) ),
           SLOT( defaultAction( QListBoxItem * ) ) );
  connect( mItemList, SIGNAL( rightButtonPressed( QListBoxItem *,
                                                  const QPoint &) ),
           SLOT( contextMenu( QListBoxItem * ) ) );
   connect( mItemList, SIGNAL( highlighted( QListBoxItem *) ),
       SLOT( selection( QListBoxItem * ) ) );
  connect( mItemList, SIGNAL( clicked( QListBoxItem * ) ),
           SLOT( cellClicked( QListBoxItem * ) ) );  
  connect( mItemList, SIGNAL( clicked( QListBoxItem * ) ),
         SLOT( selection( QListBoxItem * ) ) ); 
}

void MonthViewCell::setDate( const QDate &date )
{
//  kdDebug() << "MonthViewCell::setDate(): " << date.toString() << endl;

  mDate = date;

  QString text;
  bool smallDisplay = QApplication::desktop()->width() < 320 && KOPrefs::instance()->mMonthViewSatSunTog;
   if ( KOGlobals::self()->calendarSystem()->day( date ) == 1 || (date.dayOfWeek() == 7 && !smallDisplay ) || KOPrefs::instance()->mMonthShowShort) { 
     text = KOGlobals::self()->calendarSystem()->monthName( date, true ) + " ";
    mLabel->resize( mLabelBigSize  );
    text += QString::number( KOGlobals::self()->calendarSystem()->day(mDate) );
  } else {
    mLabel->resize( mLabelSize );
    text += QString::number( KOGlobals::self()->calendarSystem()->day(mDate) );
  }
  mLabel->setText( text );

  //resizeEvent( 0 );
}

QDate MonthViewCell::date() const
{
  return mDate;
}

void MonthViewCell::setPrimary( bool primary )
{
    mPrimary = primary;
    //setMyPalette();
}
void MonthViewCell::setMyPalette()
{
    
    if ( mHoliday) {
        setPalette( mHolidayPalette );
    } else {
        if ( mPrimary ) {
            setPalette( mPrimaryPalette );
        } else {
            setPalette( mNonPrimaryPalette );
        }
    }
    QPalette pal = palette();
    
    mLabel->setPalette( QPalette ( pal.color( QPalette::Normal,QColorGroup::Base),pal.color(QPalette::Normal,QColorGroup::Base )  ));
}
QPalette  MonthViewCell::getPalette ()
{
    if ( !KOPrefs::instance()->mMonthViewUsesDayColors )
        return mStandardPalette;
    if ( mHoliday) {
        return mHolidayPalette ;
    } else {
        if ( mPrimary ) {
            return mPrimaryPalette ;
        } 
    }
    return mNonPrimaryPalette; 
}
bool MonthViewCell::isPrimary() const
{
  return mPrimary;
}

void MonthViewCell::setHoliday( bool holiday )
{
  mHoliday = holiday; 
  //setMyPalette();
}

void MonthViewCell::setHoliday( const QString &holiday )
{
  mHolidayString = holiday;

  if ( !holiday.isEmpty() ) {
    setHoliday( true );
  }
}
void MonthViewCell::keyPressEvent ( QKeyEvent * e )
{

     e->ignore();

}
void MonthViewCell::updateCell()
{
  
    setPrimary( mDate.month()%2 );
    setHoliday( KOGlobals::self()->calendarSystem()->dayOfWeek(mDate) == KOGlobals::self()->calendarSystem()->weekDayOfPray() );
    if ( mDate == QDate::currentDate()  ) {
        mItemList->setLineWidth( 3 );
    } else {
            mItemList->setLineWidth( 1 );
    }
    mItemList->clear();
    //qApp->processEvents();
    if ( !mHolidayString.isEmpty() ) {
        MonthViewItem *item = new MonthViewItem( 0, mDate, mHolidayString );
        item->setPalette( mHolidayPalette );
        mItemList->insertItem( item );
    }
    //mLabel->setMaximumWidth( width() - mItemList->lineWidth()*2);
    QPtrList<Event> events = mMonthView->calendar()->events( mDate, true );
    Event *event;
    for( event = events.first(); event; event = events.next() ) {
        if ( event->categories().contains("Holiday") ||
             event->categories().contains(i18n("Holiday"))) {
            setHoliday( true );
            if ( mDate.dayOfWeek() == 7 )
                mItemList->setLineWidth( 3 );
        }
        QString text;
        if (event->isMultiDay()) {
            QString prefix = "<->";
            if ( event->doesRecur() ) {
                if ( event->recursOn( mDate) )
                    prefix ="->" ;
                else {
                    int days =  event->dtStart().date().daysTo ( event->dtEnd().date() );
                    if ( event->recursOn( mDate.addDays( -days)) )
                        prefix ="<-" ;
                } 

            } else {
                if (mDate == event->dtStart().date()) {
                    prefix ="->" ;
                } else if (mDate == event->dtEnd().date()) {
                    prefix ="<-" ;
                }
            }
            text = prefix + event->summary();
        } else {
            if (event->doesFloat())
                text = event->summary();
            else {
                text = KGlobal::locale()->formatTime(event->dtStart().time());
                text += " " + event->summary();
            }
        }

        MonthViewItem *item = new MonthViewItem( event, mDate, text );
        QPalette pal;
        if (KOPrefs::instance()->mMonthViewUsesCategoryColor) {    
            QStringList categories = event->categories();
            QString cat = categories.first();
            if ( KOPrefs::instance()->mMonthViewUsesForegroundColor ) {
                pal = getPalette();
                if (cat.isEmpty()) {
                    pal.setColor(QColorGroup::Foreground,KOPrefs::instance()->mEventColor);
                } else {
                    pal.setColor(QColorGroup::Foreground, *(KOPrefs::instance()->categoryColor(cat)));
                }

            } else {
                if (cat.isEmpty()) {
                    pal = QPalette(KOPrefs::instance()->mEventColor, KOPrefs::instance()->mEventColor);
                } else {
                    pal = QPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat)));
                } 
            }
           
        } else {
            pal = mStandardPalette ;
        }
        item->setPalette( pal );
        item->setRecur( event->recurrence()->doesRecur() );
        item->setAlarm( event->isAlarmEnabled() );
        item->setMoreInfo( event->description().length() > 0  );
        Attendee *me = event->attendeeByMails(KOPrefs::instance()->mAdditionalMails,
                                              KOPrefs::instance()->email());
        if ( me != 0 ) {
            if ( me->status() == Attendee::NeedsAction && me->RSVP())
                item->setReply(true);
            else
                item->setReply(false);
        } else
            item->setReply(false);
        bool insert = true;
        if ( !(event->doesRecur() == Recurrence::rNone) ) {
            if ( !KOPrefs::instance()->mMonthDailyRecur && event->doesRecur() == Recurrence::rDaily )
                insert = false;
            else
                if ( !KOPrefs::instance()->mMonthWeeklyRecur && event->doesRecur() == Recurrence::rWeekly )
                    insert = false;

        }
        if ( insert )
            mItemList->insertItem( item );
    }

    // insert due todos
    QPtrList<Todo> todos = mMonthView->calendar()->todos( mDate );
    Todo *todo;
    for(todo = todos.first(); todo; todo = todos.next()) {
        QString text;
        if (todo->hasDueDate()) {
            if (!todo->doesFloat()) {
                text += KGlobal::locale()->formatTime(todo->dtDue().time());
                text += " ";
            }
        }
        text += i18n("To-Do: %1").arg(todo->summary());

        MonthViewItem *item = new MonthViewItem( todo, mDate, text );
        //item->setPalette( mStandardPalette );
        QPalette pal;
        if (KOPrefs::instance()->mMonthViewUsesCategoryColor) {    
            QStringList categories = todo->categories();
            QString cat = categories.first();
            if ( KOPrefs::instance()->mMonthViewUsesForegroundColor ) {
                pal = getPalette();
                if (cat.isEmpty()) {
                    pal.setColor(QColorGroup::Foreground,KOPrefs::instance()->mEventColor);
                } else {
                    pal.setColor(QColorGroup::Foreground, *(KOPrefs::instance()->categoryColor(cat)));
                }

            } else {
                if (cat.isEmpty()) {
                    pal = QPalette(KOPrefs::instance()->mEventColor, KOPrefs::instance()->mEventColor);
                } else {
                    pal = QPalette(*(KOPrefs::instance()->categoryColor(cat)), *(KOPrefs::instance()->categoryColor(cat)));
                } 
            }
           
        } else {
            pal = mStandardPalette ;
        }
        item->setPalette( pal );
        mItemList->insertItem( item );
    }
    //setMyPalette(); 
    setMyPalette();
    resizeEvent( 0 );
    // if ( isVisible())
    //   qApp->processEvents();
}

void MonthViewCell::updateConfig()
{

  setFont( KOPrefs::instance()->mMonthViewFont );

  QFontMetrics fm( font() );
  mLabelSize = fm.size( 0, "30" ) + QSize( 4, 2 );
  mLabelBigSize = fm.size( 0, "Mag 30" ) + QSize( 2, 2 );
  mHolidayPalette = mStandardPalette;
  mPrimaryPalette = mStandardPalette;
  mNonPrimaryPalette = mStandardPalette;
  if ( KOPrefs::instance()->mMonthViewUsesDayColors ) {
      mHolidayPalette.setColor(QColorGroup::Base, KOPrefs::instance()->mMonthViewHolidayColor  );
      mHolidayPalette.setColor(QColorGroup::Background, KOPrefs::instance()->mMonthViewHolidayColor  );
      mHolidayPalette.setColor(QColorGroup::Foreground,  KOPrefs::instance()->mMonthViewHolidayColor.dark());
      mPrimaryPalette.setColor(QColorGroup::Foreground,KOPrefs::instance()->mMonthViewOddColor.dark());
      mPrimaryPalette.setColor(QColorGroup::Base,KOPrefs::instance()->mMonthViewOddColor);
      mPrimaryPalette.setColor(QColorGroup::Background,KOPrefs::instance()->mMonthViewOddColor);
      mNonPrimaryPalette.setColor(QColorGroup::Foreground,KOPrefs::instance()->mMonthViewEvenColor.dark());
      mNonPrimaryPalette.setColor(QColorGroup::Base,KOPrefs::instance()->mMonthViewEvenColor); 
      mNonPrimaryPalette.setColor(QColorGroup::Background,KOPrefs::instance()->mMonthViewEvenColor); 
  }
  updateCell(); 
}

void MonthViewCell::enableScrollBars( bool enabled )
{
  if ( enabled ) {
    mItemList->setVScrollBarMode(QScrollView::Auto);
    mItemList->setHScrollBarMode(QScrollView::Auto);
  } else {
    mItemList->setVScrollBarMode(QScrollView::AlwaysOff);
    mItemList->setHScrollBarMode(QScrollView::AlwaysOff);
  }
}

Incidence *MonthViewCell::selectedIncidence()
{
  int index = mItemList->currentItem();
  if ( index < 0 ) return 0;
  
  MonthViewItem *item =
      static_cast<MonthViewItem *>( mItemList->item( index ) );

  if ( !item ) return 0;
  
  return item->incidence();
}

QDate MonthViewCell::selectedIncidenceDate()
{
  QDate qd;
  int index = mItemList->currentItem();
  if ( index < 0 ) return qd;
  
  MonthViewItem *item =
      static_cast<MonthViewItem *>( mItemList->item( index ) );

  if ( !item ) return qd;
  
  return item->incidenceDate();
}

void MonthViewCell::deselect()
{
  mItemList->clearSelection();
  enableScrollBars( false );
  // updateCell();
}
void MonthViewCell::select()
{
    ;// updateCell();
}

void MonthViewCell::resizeEvent ( QResizeEvent * )
{
    int size = height() - mLabel->height();
    if ( size > 0 )
        mItemList->verticalScrollBar()->setMaximumHeight( size );
    size = width() - mLabel->width();
    if ( size > 0 )
        mItemList->horizontalScrollBar()->setMaximumWidth( size );
    mLabel->move( width()-mItemList->lineWidth() - mLabel->width(), height()-mItemList->lineWidth() - mLabel->height() );
    //mLabel->setMaximumWidth( width() - mItemList->lineWidth()*2);
}

void MonthViewCell::defaultAction( QListBoxItem *item )
{
  if ( !item ) return;

  MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
  Incidence *incidence = eventItem->incidence();
  if ( incidence ) mMonthView->defaultAction( incidence );
}
void MonthViewCell::newEvent()
{
    QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
    emit newEventSignal( dt );
}
void MonthViewCell::cellClicked( QListBoxItem *item )
{
    static  QListBoxItem * lastClicked = 0;
    if ( item == 0 ) {
        QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
        emit newEventSignal( dt );
        return;
    }
  /*
  if ( lastClicked )
      if ( ! item ) {
          if ( lastClicked->listBox() != item->listBox() )
              lastClicked->listBox()->clearSelection();
      }
  */
 
  mMonthView->setSelectedCell( this );
  if( KOPrefs::instance()->mEnableMonthScroll ) enableScrollBars( true );
  select();
}

void MonthViewCell::contextMenu( QListBoxItem *item )
{
  if ( !item ) return;
  
  MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
  Incidence *incidence = eventItem->incidence();
  if ( incidence ) mMonthView->showContextMenu( incidence );
}

void MonthViewCell::selection( QListBoxItem *item )
{
  if ( !item ) return;

  mMonthView->setSelectedCell( this );
}


// *******************************************************************************
// *******************************************************************************
// *******************************************************************************


KOMonthView::KOMonthView(Calendar *calendar, QWidget *parent, const char *name)
    : KOEventView( calendar, parent, name ),
      mDaysPerWeek( 7 ), mNumWeeks( 6 ), mNumCells( mDaysPerWeek * mNumWeeks ),
      mShortDayLabels( false ), mWidthLongDayLabel( 0 ), mSelectedCell( 0 )
{
  mCells.setAutoDelete( true );
  mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ;
  // mDayLayout = new QGridLayout( this );
  // create the day of the week labels (Sun, Mon, etc) and add them to
  // the layout.
  mDayLabels.resize( mDaysPerWeek );
  QFont bfont = font();
  if ( QApplication::desktop()->width() < 650 ) {
      bfont.setPointSize( bfont.pointSize() - 2 );
  }
  bfont.setBold( true );
  int i;
  
  for( i = 0; i < mDaysPerWeek; i++ ) {
    QLabel *label = new QLabel( this );
    label->setFont(bfont);
    label->setFrameStyle(QFrame::Panel|QFrame::Raised);
    label->setLineWidth(1);
    label->setAlignment(AlignCenter);
    mDayLabels.insert( i, label );
  }

  bfont.setBold( false );
  mWeekLabels.resize( mNumWeeks+1 );
  for( i = 0; i < mNumWeeks+1; i++ ) {
      KOWeekButton *label = new KOWeekButton( this );
      label->setFont(bfont);
      connect( label, SIGNAL( selectWeekNum ( int )),this, SIGNAL( selectWeekNum ( int ))   );  
      label->setFlat(true);
      QWhatsThis::add(label,i18n("Click on the week number to\nshow week in agenda view"));
      //label->setFrameStyle(QFrame::Panel|QFrame::Raised);
      //label->setLineWidth(1);
      //label->setAlignment(AlignCenter);
      mWeekLabels.insert( i, label );
  }
  mWeekLabels[mNumWeeks]->setText( i18n("W"));
  int row, col;
  mCells.resize( mNumCells );
  for( row = 0; row < mNumWeeks; ++row ) {
    for( col = 0; col < mDaysPerWeek; ++col ) {
      MonthViewCell *cell = new MonthViewCell( this );
      mCells.insert( row * mDaysPerWeek + col, cell );

      connect( cell, SIGNAL( defaultAction( Incidence * ) ),
               SLOT( defaultAction( Incidence * ) ) );
      connect( cell, SIGNAL( newEventSignal( QDateTime ) ),
               SIGNAL( newEventSignal( QDateTime ) ) );
    }
  }

  mContextMenu = eventPopup();
  // updateConfig(); //useless here

  emit incidenceSelected( 0 );
}

KOMonthView::~KOMonthView()
{
  delete mContextMenu;
}

int KOMonthView::maxDatesHint()
{
  return mNumCells;
}

int KOMonthView::currentDateCount()
{
  return mNumCells;
}

QPtrList<Incidence> KOMonthView::selectedIncidences()
{
  QPtrList<Incidence> selected;

  if ( mSelectedCell ) {
    Incidence *incidence = mSelectedCell->selectedIncidence();
    if ( incidence ) selected.append( incidence );
  }

  return selected;
}

DateList KOMonthView::selectedDates()
{
  DateList selected;

  if ( mSelectedCell ) {
    QDate qd = mSelectedCell->selectedIncidenceDate();
    if ( qd.isValid() ) selected.append( qd );
  }

  return selected;
}

void KOMonthView::printPreview(CalPrinter *calPrinter, const QDate &fd,
                               const QDate &td)
{
#ifndef KORG_NOPRINTER
  calPrinter->preview(CalPrinter::Month, fd, td);
#endif
}

void KOMonthView::updateConfig()
{
 
  mWeekStartsMonday = KGlobal::locale()->weekStartsMonday();

  QFontMetrics fontmetric(mDayLabels[0]->font());
  mWidthLongDayLabel = 0;

  for (int i = 0; i < 7; i++) {
    int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1));
    if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width;
  }
  bool temp = mShowSatSunComp ;
  mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ;
  if ( temp != KOPrefs::instance()->mMonthViewSatSunTog )
      computeLayout();
  updateDayLabels();
  //qDebug("KOMonthView::updateConfig() %d %d %d ",height(), mDayLabels[0]->sizeHint().height() ,mNumWeeks);
  int cellHeight = (height() - mDayLabels[0]->sizeHint().height()) /mNumWeeks;
  //resizeEvent( 0 );
   for (uint i = 0; i < mCells.count(); ++i) {
    mCells[i]->updateConfig();
  }
}

void KOMonthView::updateDayLabels()
{
  
  for (int i = 0; i < 7; i++) {
    if (mWeekStartsMonday) {
        bool show = mShortDayLabels;
        if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > mDayLabels[i]->width()  )
            show = true;
        mDayLabels[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show));
    } else {
       if (i==0) mDayLabels[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabels));
       else mDayLabels[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabels));

    }
  }
}

void KOMonthView::showDates(const QDate &start, const QDate &)
{
//  kdDebug() << "KOMonthView::showDates(): " << start.toString() << endl;


  mStartDate = start;

  int startWeekDay = mWeekStartsMonday ? 1 : 7;

   while( KOGlobals::self()->calendarSystem()->dayOfWeek(mStartDate) != startWeekDay ) {
    mStartDate = mStartDate.addDays( -1 );
  }

  bool primary = false;
  uint i;
  for( i = 0; i < mCells.size(); ++i ) {
    QDate date = mStartDate.addDays( i );
    mCells[i]->setDate( date );

#ifndef KORG_NOPLUGINS
    // add holiday, if present
    QString hstring(KOCore::self()->holiday(date));
    mCells[i]->setHoliday( hstring );
#endif

  }
  QDate date = mStartDate.addDays( mWeekStartsMonday ? 3 : 4 );
  for( i = 0; i < 6; ++i ) {
    int wno;
    // remember, according to ISO 8601, the first week of the year is the
    // first week that contains a thursday.  Thus we must subtract off 4,
    // not just 1.
     int dayOfYear = date.dayOfYear();
    if (dayOfYear % 7 != 0)
      wno = dayOfYear / 7 + 1;
    else
      wno =dayOfYear / 7;
    mWeekLabels[i]->setWeekNum( wno );
    date = date.addDays( 7 );
  }
  updateView();
}

void KOMonthView::showEvents(QPtrList<Event>)
{
    qDebug("KOMonthView::selectEvents is not implemented yet. ");
}

void KOMonthView::changeEventDisplay(Event *, int)
{
  // this should be re-written to be much more efficient, but this
  // quick-and-dirty-hack gets the job done for right now.
  updateView();
}

void KOMonthView::updateView()
{
 
  uint i;
  for( i = 0; i < mCells.count(); ++i ) {
    mCells[i]->updateCell();
  }
  //qDebug("KOMonthView::updateView() ");
  processSelectionChange();
}

void KOMonthView::resizeEvent(QResizeEvent * e)
{
    computeLayout();
}
void KOMonthView::computeLayout()
{
  // select the appropriate heading string size. E.g. "Wednesday" or "Wed".
  // note this only changes the text if the requested size crosses the
  // threshold between big enough to support the full name and not big
  // enough.

    int daysToShow = 7;
    bool combinedSatSun  = false;
    if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) {
        daysToShow = 6;
        combinedSatSun  = true;
    }
    int tWid = topLevelWidget()->size().width();
    int tHei = topLevelWidget()->size().height();

    int wid = size().width();//e
    int hei = size().height()-1;

    if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei  ) 
        return;

    QFontMetrics fm ( mWeekLabels[0]->font() );
    int weeklabelwid = fm.width( "888" );
    wid -= weeklabelwid;

    int colWid = wid / daysToShow;
    int lastCol = wid - ( colWid*6  ); 
    int dayLabelHei = mDayLabels[0]->sizeHint().height();
    int cellHei = (hei - dayLabelHei) /6; 
    int colModulo = wid % daysToShow;
    int rowModulo = (hei- dayLabelHei) % 6;
    //qDebug("rowmod %d ", rowModulo);
    int i;
    int x,y,w,h;
    x= 0;
    y= 0;
    w = colWid;
    h = dayLabelHei ;
    for ( i = 0; i < 7; i++) {
        if ( i == daysToShow-colModulo )
            ++w;
        if ( combinedSatSun ) {
            if ( i >=  daysToShow-1 ) {
                mDayLabels[i]->setGeometry( x+weeklabelwid,y,w/2,h);
                x -= w/2 ;
            }
            else
                mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h);
        } else
            mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h);
        x += w;                                   
    }
    x= 0;
    y= dayLabelHei;
    w = colWid;
    h = cellHei ;
    for ( i = 0; i < mCells.count(); ++i) {
        
        w = colWid;
        if ( ((i) % 7) >= 7-colModulo ) {
            ++w;
        }
        if ( i  == (6-rowModulo)*7)
            ++h; 
        if ( combinedSatSun ) {
            if ( (i)%7 >=  daysToShow-1 ) {
                if ( (i)%7 ==  daysToShow-1 ) {
                    mCells[i]->setGeometry ( x+weeklabelwid,y,w,h/2 ); 
                    x -= w ;y += h/2;
                } else {
                    mCells[i]->setGeometry ( x+weeklabelwid,y,w,h-h/2 ); 
                    y -= h/2;
                }
            } else
                mCells[i]->setGeometry ( x+weeklabelwid,y,w,h ); 
                
        }
        else
            mCells[i]->setGeometry ( x+weeklabelwid,y,w,h );
        x += w;
        if ( x + w/2 > wid ) {
            x = 0;
            y += h;
        }
    }
    y= dayLabelHei;
    h = cellHei ;
    for ( i = 0; i < 6; i++) {
        if ( i  == (6-rowModulo))
            ++h;
        mWeekLabels[i]->setGeometry( 0,y,weeklabelwid,h);
        y += h;                            
    }
    mWeekLabels[6]->setGeometry( 0,0,weeklabelwid,dayLabelHei);
    // qDebug("RRRRRRRRRRRRR %d %d  old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height());
    //qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height());
    mShortDayLabels = mDayLabels[0]->width() < mWidthLongDayLabel ;
    updateDayLabels();
}

void KOMonthView::showContextMenu( Incidence *incidence )
{
  mContextMenu->showIncidencePopup(incidence);
  /*
  if( incidence && incidence->type() == "Event" ) {
    Event *event = static_cast<Event *>(incidence);
    mContextMenu->showEventPopup(event);
  } else {
    kdDebug() << "MonthView::showContextMenu(): cast failed." << endl;
  }
  */
}
MonthViewCell * KOMonthView::selectedCell( )
{
    return mSelectedCell;
}
void KOMonthView::setSelectedCell( MonthViewCell *cell )
{
    // qDebug("KOMonthView::setSelectedCell ");
    if ( mSelectedCell && mSelectedCell != cell ) {
        MonthViewCell * mvc = mSelectedCell;
        mSelectedCell = cell;
        mvc->deselect();
    } else 
        mSelectedCell = cell;
   //  if ( mSelectedCell )
//         mSelectedCell->select();
  if ( !mSelectedCell )
    emit incidenceSelected( 0 );
  else 
    emit incidenceSelected( mSelectedCell->selectedIncidence() );
}

void KOMonthView::processSelectionChange()
{
  QPtrList<Incidence> incidences = selectedIncidences();
  if (incidences.count() > 0) {
    emit incidenceSelected( incidences.first() );
  } else {
    emit incidenceSelected( 0 );
  }
}

void KOMonthView::clearSelection()
{
  if ( mSelectedCell ) {
    mSelectedCell->deselect();
    mSelectedCell = 0;
  }
}
void KOMonthView::keyPressEvent ( QKeyEvent * e )
{
    
    e->ignore();
   
}