/*
  This file is part of KAddressBook.
  Copyright (c) 2002 Jost Schenck <jost@schenck.de>
                2009 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 Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "ringbinderstyle.h"
#include "printingwizard.h"
#include "printprogress.h"
#include "ui_rbs_appearance.h"

#include <KConfig>
#include <KGlobal>
#include <KLocale>

#include <QPrinter>
#include <QTextDocument>

using namespace KABPrinting;

const char *RingBinderConfigSectionName = "RingBinderPrintStyle";
const char *ShowPhoneNumbers = "ShowPhoneNumbers";
const char *ShowEmailAddresses = "ShowEmailAddresses";
const char *ShowStreetAddresses = "ShowStreetAddresses";
const char *ShowOrganization = "ShowOrganization";
const char *ShowBirthday = "ShowBirthday";
const char *ShowNote = "ShowNote";

enum PrintField {
  PhoneNumbers = 1,
  Emails = 2,
  Addresses = 4,
  Organization = 8,
  Birthday = 16,
  Note = 32
};

static QString contactsToHtml( const KABC::Addressee::List &contacts, int fields )
{
  QString content;

  content += "<html>\n";
  content += " <body>\n";
  content += "  <table style=\"border-width: 1px; border-style: solid; "
             "border-color: gray;\" width=\"100%\" cellspacing=\"0\">\n";
  foreach ( const KABC::Addressee &contact, contacts ) {
    QString nameString = contact.familyName() + ", " + contact.givenName();

    if ( fields & Organization ) {
      if ( !contact.organization().isEmpty() ) {
        nameString += " (" + contact.organization() + ')';
      }
    }

    if ( fields & Birthday ) {
      if ( contact.birthday().isValid() ) {
        nameString += " *" + KGlobal::locale()->formatDate( contact.birthday().date(),
                                                            KLocale::ShortDate );
      }
    }

    QStringList leftBlock, rightBlock;
    if ( fields & PhoneNumbers ) {
      const KABC::PhoneNumber::List numbers = contact.phoneNumbers();
      foreach ( const KABC::PhoneNumber &number, numbers ) {
        rightBlock.append( number.typeLabel() + ": " + number.number() );
      }
    }
    if ( fields & Emails ) {
      const QStringList emails = contact.emails();
      foreach ( const QString &email, emails ) {
        rightBlock.append( email );
      }
    }
    if ( fields & Note ) {
      if ( !contact.note().isEmpty() ) {
        const QString note = QLatin1String( "Note: " ) + contact.note().replace( '\n', "<br/>" );

        rightBlock.append( note );
      }
    }
    if ( fields & Addresses ) {
      const KABC::Address::List addresses = contact.addresses();
      foreach ( const KABC::Address &address, addresses ) {
        const QString data =
          address.formattedAddress().replace( "\n\n", "\n" ).replace( '\n', "<br/>" );
        const QString subBlock= "<p style=\"margin-top: 0px; margin-left: 20px\">" + data + "</p>";

        leftBlock.append( subBlock );
      }
    }

    content += "   <tr>\n";
    content += "    <td style=\"padding-left: 3px; padding-top: 3px; padding-right: 3px; "
               "padding-bottom: 3px;\">" +
               nameString + leftBlock.join( QString() ) + "</td>\n";
    content += "    <td style=\"padding-left: 3px; padding-top: 3px; padding-right: 3px; "
               "padding-bottom: 3px;\">" +
               rightBlock.join( "<br/>" ) + "</td>\n";
    content += "   </tr>\n";
  }
  content += "  </table>\n";
  content += " </body>\n";
  content += "</html>\n";

  return content;
}

namespace KABPrinting
{

class RingBinderStyleAppearanceForm : public QWidget, public Ui::RingBinderStyleAppearanceForm_Base
{
  public:
    explicit RingBinderStyleAppearanceForm( QWidget *parent )
      : QWidget( parent )
    {
      setObjectName( "AppearancePage" );
      setupUi( this );
    }
};

}

RingBinderPrintStyle::RingBinderPrintStyle( PrintingWizard *parent )
  : PrintStyle( parent ),
    mPageAppearance( new RingBinderStyleAppearanceForm( parent ) )
{
  setPreview( "ringbinder-style.png" );
  setPreferredSortOptions( ContactFields::FamilyName, Qt::AscendingOrder );

  addPage( mPageAppearance, i18n( "Ring Binder Printing Style - Appearance" ) );

  // applying previous settings
  KConfigGroup config( KGlobal::config(), RingBinderConfigSectionName );
  mPageAppearance->cbPhoneNumbers->setChecked( config.readEntry( ShowPhoneNumbers, true ) );
  mPageAppearance->cbEmails->setChecked( config.readEntry( ShowEmailAddresses, true ) );
  mPageAppearance->cbStreetAddresses->setChecked( config.readEntry( ShowStreetAddresses, true ) );
  mPageAppearance->cbOrganization->setChecked( config.readEntry( ShowOrganization, true ) );
  mPageAppearance->cbBirthday->setChecked( config.readEntry( ShowBirthday, false ) );
  mPageAppearance->cbNote->setChecked( config.readEntry( ShowNote, false ) );
}

RingBinderPrintStyle::~RingBinderPrintStyle()
{
}

void RingBinderPrintStyle::print( const KABC::Addressee::List &contacts, PrintProgress *progress )
{
  progress->addMessage( i18n( "Setting up fields" ) );
  progress->setProgress( 0 );

  // first write current config settings
  KConfigGroup config( KGlobal::config(), RingBinderConfigSectionName );
  config.writeEntry( ShowPhoneNumbers, mPageAppearance->cbPhoneNumbers->isChecked() );
  config.writeEntry( ShowEmailAddresses, mPageAppearance->cbEmails->isChecked() );
  config.writeEntry( ShowStreetAddresses, mPageAppearance->cbStreetAddresses->isChecked() );
  config.writeEntry( ShowOrganization, mPageAppearance->cbOrganization->isChecked() );
  config.writeEntry( ShowBirthday, mPageAppearance->cbBirthday->isChecked() );
  config.writeEntry( ShowNote, mPageAppearance->cbNote->isChecked() );
  config.sync();

  QPrinter *printer = wizard()->printer();
  printer->setPageMargins( 50, 20, 0, 50, QPrinter::DevicePixel );

  progress->addMessage( i18n( "Setting up document" ) );

  int fields = 0;

  if ( mPageAppearance->cbPhoneNumbers->isChecked() ) {
    fields |= PhoneNumbers;
  }

  if ( mPageAppearance->cbEmails->isChecked() ) {
    fields |= Emails;
  }

  if ( mPageAppearance->cbStreetAddresses->isChecked() ) {
    fields |= Addresses;
  }

  if ( mPageAppearance->cbOrganization->isChecked() ) {
    fields |= Organization;
  }

  if ( mPageAppearance->cbBirthday->isChecked() ) {
    fields |= Birthday;
  }

  if ( mPageAppearance->cbNote->isChecked() ) {
    fields |= Note;
  }

  const QString html = contactsToHtml( contacts, fields );

  QTextDocument document;
  document.setHtml( html );

  progress->addMessage( i18n( "Printing" ) );

  document.print( printer );

  progress->addMessage( i18nc( "Finished printing", "Done" ) );
}

RingBinderPrintStyleFactory::RingBinderPrintStyleFactory( PrintingWizard *parent )
  : PrintStyleFactory( parent )
{
}

PrintStyle *RingBinderPrintStyleFactory::create() const
{
  return new RingBinderPrintStyle( mParent );
}

QString RingBinderPrintStyleFactory::description() const
{
  return i18n( "Printout for Ring Binders" );
}
