/*
    This file is part of Kontact.
    Copyright (c) 2003 Tobias Koenig <tokoe@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of TQt, and distribute the resulting executable,
    without including the source code for TQt in the source distribution.
*/

#include <tqcursor.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqtooltip.h>

#include <kdialog.h>
#include <tdeglobal.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdeparts/part.h>
#include <tdepopupmenu.h>
#include <kstandarddirs.h>
#include <kurllabel.h>
#include <libkcal/event.h>
#include <libkcal/resourcecalendar.h>
#include <libkcal/resourcelocal.h>
#include <libkcal/incidenceformatter.h>
#include <libtdepim/kpimprefs.h>

#include "korganizeriface_stub.h"

#include "core.h"
#include "plugin.h"
#include "korganizerplugin.h"

#include "korganizer/stdcalendar.h"

#include "summarywidget.h"

SummaryWidget::SummaryWidget( KOrganizerPlugin *plugin, TQWidget *parent,
                              const char *name )
  : Kontact::Summary( parent, name ), mPlugin( plugin ), mCalendar( 0 )
{
  TQVBoxLayout *mainLayout = new TQVBoxLayout( this, 3, 3 );

  TQPixmap icon = TDEGlobal::iconLoader()->loadIcon( "kontact_date",
                   TDEIcon::Desktop, TDEIcon::SizeMedium );
  TQWidget *header = createHeader( this, icon, i18n( "Calendar" ) );
  mainLayout->addWidget( header );

  mLayout = new TQGridLayout( mainLayout, 7, 5, 3 );
  mLayout->setRowStretch( 6, 1 );

  mCalendar = KOrg::StdCalendar::self();

  connect( mCalendar, TQT_SIGNAL( calendarChanged() ), TQT_SLOT( updateView() ) );
  connect( mPlugin->core(), TQT_SIGNAL( dayChanged( const TQDate& ) ),
           TQT_SLOT( updateView() ) );

  updateView();
}

SummaryWidget::~SummaryWidget()
{
}

void SummaryWidget::updateView()
{
  mLabels.setAutoDelete( true );
  mLabels.clear();
  mLabels.setAutoDelete( false );

  TDEIconLoader loader( "tdepim" );

  TDEConfig config( "kcmkorgsummaryrc" );

  config.setGroup( "Calendar" );
  int days = config.readNumEntry( "DaysToShow", 1 );

  TQLabel *label = 0;
  int counter = 0;
  TQPixmap pm = loader.loadIcon( "appointment", TDEIcon::Small );
  TQPixmap pmb = loader.loadIcon( "calendarbirthday", TDEIcon::Small );
  TQPixmap pma = loader.loadIcon( "calendaranniversary", TDEIcon::Small );

  TQDate dt;
  TQDate currentDate = TQDate::currentDate();
  for ( dt=currentDate;
        dt<=currentDate.addDays( days - 1 );
        dt=dt.addDays(1) ) {

    KCal::Event::List events = mCalendar->events( dt );

    // sort the events for this date by summary
    events = KCal::Calendar::sortEventsForDate( &events,
                                                dt,
                                                KCal::EventSortSummary,
                                                KCal::SortDirectionAscending );
    // sort the events for this date by start date
    events = KCal::Calendar::sortEventsForDate( &events,
                                                dt,
                                                KCal::EventSortStartDate,
                                                KCal::SortDirectionAscending );

    KCal::Event::List::ConstIterator it = events.begin();
    for ( it=events.begin(); it!=events.end(); ++it ) {
      KCal::Event *ev = *it;

      // Count number of days remaining in multiday event
      int span=1; int dayof=1;
      if ( ev->isMultiDay() ) {
        TQDate d = ev->dtStart().date();
        if ( d < currentDate ) {
          d = currentDate;
        }
        while ( d < ev->dtEnd().date() ) {
          if ( d < dt ) {
            dayof++;
          }
          span++;
          d=d.addDays( 1 );
        }
      }

      // If this date is part of a floating, multiday event, then we
      // only make a print for the first day of the event.
      if ( ev->isMultiDay() && ev->doesFloat() && dayof != 1 ) continue;

      // Fill Appointment Pixmap Field
      label = new TQLabel( this );
      if ( ev->categories().contains( "Birthday" ) ) {
        label->setPixmap( pmb );
      } else if ( ev->categories().contains( "Anniversary" ) ) {
        label->setPixmap( pma );
      } else {
        label->setPixmap( pm );
      }
      label->setMaximumWidth( label->minimumSizeHint().width() );
      label->setAlignment( AlignVCenter );
      mLayout->addWidget( label, counter, 0 );
      mLabels.append( label );

      // Fill Event Date Field
      bool makeBold = false;
      TQString datestr;

      // Modify event date for printing
      TQDate sD = TQDate( dt.year(), dt.month(), dt.day() );
      if ( ( sD.month() == currentDate.month() ) &&
           ( sD.day()   == currentDate.day() ) ) {
        datestr = i18n( "Today" );
        makeBold = true;
      } else if ( ( sD.month() == currentDate.addDays( 1 ).month() ) &&
                  ( sD.day()   == currentDate.addDays( 1 ).day() ) ) {
        datestr = i18n( "Tomorrow" );
      } else {
        datestr = TDEGlobal::locale()->formatDate( sD );
      }

      // Print the date span for multiday, floating events, for the
      // first day of the event only.
      if ( ev->isMultiDay() && ev->doesFloat() && dayof == 1 && span > 1 ) {
        datestr = TDEGlobal::locale()->formatDate( ev->dtStart().date() );
        datestr += " -\n " +
                   TDEGlobal::locale()->formatDate( sD.addDays( span-1 ) );
      }

      label = new TQLabel( datestr, this );
      label->setAlignment( AlignLeft | AlignVCenter );
      if ( makeBold ) {
        TQFont font = label->font();
        font.setBold( true );
        label->setFont( font );
      }
      mLayout->addWidget( label, counter, 1 );
      mLabels.append( label );

      // Fill Event Summary Field
      TQString newtext = ev->summary();
      if ( ev->isMultiDay() &&  !ev->doesFloat() ) {
        newtext.append( TQString(" (%1/%2)").arg( dayof ).arg( span ) );
      }

      KURLLabel *urlLabel = new KURLLabel( this );
      urlLabel->setText( newtext );
      urlLabel->setURL( ev->uid() );
      urlLabel->installEventFilter( this );
      urlLabel->setAlignment( urlLabel->alignment() | TQt::WordBreak );
      mLayout->addWidget( urlLabel, counter, 2 );
      mLabels.append( urlLabel );

      connect( urlLabel, TQT_SIGNAL( leftClickedURL( const TQString& ) ),
               this, TQT_SLOT( viewEvent( const TQString& ) ) );
      connect( urlLabel, TQT_SIGNAL( rightClickedURL( const TQString& ) ),
               this, TQT_SLOT( popupMenu( const TQString& ) ) );

      TQString tipText( KCal::IncidenceFormatter::toolTipStr( mCalendar, ev, dt, true ) );
      if ( !tipText.isEmpty() ) {
        TQToolTip::add( urlLabel, tipText );
      }

      // Fill Event Time Range Field (only for non-floating Events)
      if ( !ev->doesFloat() ) {
        TQTime sST = ev->dtStart().time();
        TQTime sET = ev->dtEnd().time();
        if ( ev->isMultiDay() ) {
          if ( ev->dtStart().date() < dt ) {
            sST = TQTime( 0, 0 );
          }
          if ( ev->dtEnd().date() > dt ) {
            sET = TQTime( 23, 59 );
          }
        }
        datestr = i18n( "Time from - to", "%1 - %2" )
                  .arg( TDEGlobal::locale()->formatTime( sST ) )
                  .arg( TDEGlobal::locale()->formatTime( sET ) );
        label = new TQLabel( datestr, this );
        label->setAlignment( AlignLeft | AlignVCenter );
        mLayout->addWidget( label, counter, 3 );
        mLabels.append( label );
      }

      counter++;
    }
  }

  if ( !counter ) {
    TQLabel *noEvents = new TQLabel(
      i18n( "No appointments pending within the next day",
            "No appointments pending within the next %n days",
            days ), this, "nothing to see" );
    noEvents->setAlignment( AlignHCenter | AlignVCenter );
    mLayout->addWidget( noEvents, 0, 2 );
    mLabels.append( noEvents );
  }

  for ( label = mLabels.first(); label; label = mLabels.next() )
    label->show();
}

void SummaryWidget::viewEvent( const TQString &uid )
{
  mPlugin->core()->selectPlugin( "kontact_korganizerplugin" ); //ensure loaded
  KOrganizerIface_stub iface( "korganizer", "KOrganizerIface" );
  iface.editIncidence( uid );
}

void SummaryWidget::removeEvent( const TQString &uid )
{
  mPlugin->core()->selectPlugin( "kontact_korganizerplugin" ); //ensure loaded
  KOrganizerIface_stub iface( "korganizer", "KOrganizerIface" );
  iface.deleteIncidence( uid, false );
}

void SummaryWidget::popupMenu( const TQString &uid )
{
  TDEPopupMenu popup( this );
  TQToolTip::remove( this );
  popup.insertItem( i18n( "&Edit Appointment..." ), 0 );
  popup.insertItem( TDEGlobal::iconLoader()->loadIcon( "edit-delete", TDEIcon::Small),
                    i18n( "&Delete Appointment" ), 1 );

  switch ( popup.exec( TQCursor::pos() ) ) {
    case 0:
      viewEvent( uid );
      break;
    case 1:
      removeEvent( uid );
      break;
  }
}

bool SummaryWidget::eventFilter( TQObject *obj, TQEvent* e )
{
  if ( obj->inherits( "KURLLabel" ) ) {
    KURLLabel* label = static_cast<KURLLabel*>( TQT_TQWIDGET(obj) );
    if ( e->type() == TQEvent::Enter )
      emit message( i18n( "Edit Appointment: \"%1\"" ).arg( label->text() ) );
    if ( e->type() == TQEvent::Leave )
      emit message( TQString() );
  }

  return Kontact::Summary::eventFilter( obj, e );
}

TQStringList SummaryWidget::configModules() const
{
  return TQStringList( "kcmkorgsummary.desktop" );
}

#include "summarywidget.moc"
