#include "addressfinder.h"
 #include <qcontactdetailfilter.h>
 #include <qcontactemailaddress.h>
 #include <qcontactmanager.h>
 #include <qcontactphonenumber.h>
 #include <qmessage.h>
 #include <qmessageservice.h>
 #include <QCheckBox>
 #include <QComboBox>
 #include <QDateTime>
 #include <QGroupBox>
 #include <QLabel>
 #include <QLayout>
 #include <QListWidget>
 #include <QMessageBox>
 #include <QPushButton>
 #include <QTimer>
 #include <QDebug>
 #include <QApplication>
 #include <QMenuBar>
 #include <QTabWidget>
 #include <QScrollArea>
 namespace {
 QString simpleAddress(const QString &recipient)
 {
     QString name;
     QString addressOnly;
     QMessageAddress::parseEmailAddress(recipient, &name, &addressOnly);
     return addressOnly;
 }
 QString simpleAddress(const QMessageAddress &address)
 {
     return simpleAddress(address.addressee());
 }
 QString contactDisplayName(const QMessageAddress &address)
 {
     QString addressOnly(simpleAddress(address));
     
     QContactDetailFilter filter;
     if (address.type() == QMessageAddress::Email) {
         
         filter.setDetailDefinitionName(QContactEmailAddress::DefinitionName, QContactEmailAddress::FieldEmailAddress);
         filter.setValue(addressOnly);
         filter.setMatchFlags(QContactFilter::MatchContains);
     } else if (address.type() == QMessageAddress::Phone) {
         
         filter.setDetailDefinitionName(QContactPhoneNumber::DefinitionName, QContactPhoneNumber::FieldNumber);
         filter.setValue(addressOnly);
         filter.setMatchFlags(QContactFilter::MatchPhoneNumber);
     }
     QContactManager manager;
     foreach (const QContactLocalId &contactId, manager.contactIds(filter)) {
         
         const QContact &contact(manager.contact(contactId));
         return contact.displayLabel();
     }
     
     return address.addressee();
 }
 }
 AddressFinder::AddressFinder(QWidget *parent, Qt::WindowFlags flags)
     : QMainWindow(parent, flags),
       tabWidget(0),
       includePeriod(0),
       excludePeriod(0),
       excludeCheckBox(0),
       searchAction(0),
       searchButton(0),
       contactList(0),
       messageCombo(0)
  {
     setupUi();
     connect(&service, SIGNAL(stateChanged(QMessageService::State)), this, SLOT(stateChanged(QMessageService::State)));
     connect(&service, SIGNAL(messagesFound(QMessageIdList)), this, SLOT(messagesFound(QMessageIdList)));
 }
 AddressFinder::~AddressFinder()
 {
 }
 void AddressFinder::includePeriodChanged(int selected)
 {
     
     excludePeriod->clear();
     switch (selected) {
         case 0: excludePeriod->insertItem(0, "9 Months"); 
         case 1: excludePeriod->insertItem(0, "6 Months");
         case 2: excludePeriod->insertItem(0, "3 Months");
         case 3: excludePeriod->insertItem(0, "Month");
         case 4: excludePeriod->insertItem(0, "Week");
         default: break;
     }
     excludePeriod->setCurrentIndex(0);
 }
 void AddressFinder::excludePeriodEnabled(int state)
 {
     excludePeriod->setEnabled(state == Qt::Checked);
 }
 void AddressFinder::addressSelected(int index)
 {
     messageCombo->clear();
     if (index == -1)
         return;
 #ifdef USE_CONTACTS_COMBOBOX
     QString address = contactList->itemData(index).toString();
 #else
     QString address = contactList->item(index)->data(Qt::UserRole).toString();
 #endif
     QString addressOnly(simpleAddress(address));
     
     typedef QPair<QString, QMessageId> MessageDetails;
     foreach (const MessageDetails &message, addressMessages[addressOnly]) {
         messageCombo->addItem(message.first);
     }
 }
 void AddressFinder::searchMessages()
 {
     setSearchActionEnabled(false);
     contactList->clear();
     messageCombo->clear();
     excludedAddresses.clear();
     addressList.clear();
     addressMessages.clear();
     inclusionMessages.clear();
     exclusionMessages.clear();
     QDateTime now(QDateTime::currentDateTime());
     bool useExclusionPeriod(excludeCheckBox->isChecked());
     
     QDateTime minimumDate(now);
     switch (includePeriod->currentIndex()) {
         case 0: minimumDate = minimumDate.addMonths(-12); break;
         case 1: minimumDate = minimumDate.addMonths(-9); break;
         case 2: minimumDate = minimumDate.addMonths(-6); break;
         case 3: minimumDate = minimumDate.addMonths(-3); break;
         case 4: minimumDate = minimumDate.addMonths(-1); break;
         case 5: minimumDate = minimumDate.addDays(-7); break;
         default: break;
     }
     QDateTime maximumDate(now);
     if (useExclusionPeriod) {
         
         switch (excludePeriod->currentIndex()) {
             case 0: maximumDate = maximumDate.addDays(-7); break;
             case 1: maximumDate = maximumDate.addMonths(-1); break;
             case 2: maximumDate = maximumDate.addMonths(-3); break;
             case 3: maximumDate = maximumDate.addMonths(-6); break;
             case 4: maximumDate = maximumDate.addMonths(-9); break;
             default: break;
         }
     }
     
     QMessageFilter includeFilter(QMessageFilter::byTimeStamp(minimumDate, QMessageDataComparator::GreaterThanEqual));
     
     includeFilter |= QMessageFilter::byReceptionTimeStamp(minimumDate, QMessageDataComparator::GreaterThanEqual);
     QMessageFilter excludeFilter;
     if (useExclusionPeriod) {
         
         excludeFilter = QMessageFilter::byTimeStamp(maximumDate, QMessageDataComparator::GreaterThanEqual);
         excludeFilter |= QMessageFilter::byReceptionTimeStamp(maximumDate, QMessageDataComparator::GreaterThanEqual);
     }
     
     QMessageFilter sentFilter(QMessageFilter::byStandardFolder(QMessage::SentFolder));
     
     if (useExclusionPeriod) {
         inclusionFilter = (sentFilter & includeFilter & ~excludeFilter);
     } else {
         inclusionFilter = (sentFilter & includeFilter);
     }
     if (useExclusionPeriod) {
         
         QMessageFilter exclusionFilter;
         exclusionFilter = (sentFilter & excludeFilter);
         
         service.queryMessages(exclusionFilter);
     } else {
         
         service.queryMessages(inclusionFilter);
         
         inclusionFilter = QMessageFilter();
     }
 }
 void AddressFinder::stateChanged(QMessageService::State newState)
 {
     if (searchAction->isEnabled() == false) {
         if (newState == QMessageService::FinishedState) {
             if (service.error() == QMessageManager::NoError) {
                 if (!inclusionFilter.isEmpty()) {
                     
                     service.queryMessages(inclusionFilter);
                     
                     inclusionFilter = QMessageFilter();
                 } else {
                     
                     if (!inclusionMessages.isEmpty()) {
                         
                         QTimer::singleShot(0, this, SLOT(continueSearch()));
                     } else {
                         QMessageBox::information(0, tr("Empty"), tr("No messages found"));
                         setSearchActionEnabled(true);
                     }
                 }
             } else {
                 QMessageBox::warning(0, tr("Failed"), tr("Unable to perform search"));
                 setSearchActionEnabled(true);
             }
         }
     }
 }
 void AddressFinder::messagesFound(const QMessageIdList &ids)
 {
     
     if (!inclusionFilter.isEmpty()) {
         exclusionMessages << ids;
     } else {
         inclusionMessages << ids;
     }
 }
 void AddressFinder::continueSearch()
 {
     if (!exclusionMessages.isEmpty()) {
         
         QMessageId id(exclusionMessages.takeFirst());
         const QMessage message(id);
         
         foreach (const QMessageAddress &address, message.to() + message.cc() + message.bcc()) {
             excludedAddresses.insert(simpleAddress(address));
         }
     } else if (!inclusionMessages.isEmpty()) {
         
         QMessageId id(inclusionMessages.takeFirst());
         const QMessage message(id);
         QString details;
         
         foreach (const QMessageAddress &address, message.to() + message.cc() + message.bcc()) {
             QString addressOnly(simpleAddress(address));
             
             if (!excludedAddresses.contains(addressOnly)) {
                 
                 QList<QPair<QString, QMessageId> > &messageList(addressMessages[addressOnly]);
                 if (messageList.isEmpty()) {
                     addressList.append(addressOnly);
                     
 #ifdef USE_CONTACTS_COMBOBOX
                     contactList->addItem(contactDisplayName(address), addressOnly);
 #else
                     QListWidgetItem* newListWidgetItem = new QListWidgetItem(contactDisplayName(address));
                     newListWidgetItem->setData(Qt::UserRole, addressOnly);
                     contactList->addItem(newListWidgetItem);
 #endif
                 }
                 if (details.isEmpty()) {
                     
                     details = QString("[%1] %2").arg(message.date().toString("MMM d")).arg(message.subject());
                 }
                 messageList.append(qMakePair(details, id));
             }
         }
     }
     if (!exclusionMessages.isEmpty() || !inclusionMessages.isEmpty()) {
         
         QTimer::singleShot(0, this, SLOT(continueSearch()));
     } else {
         
         setSearchActionEnabled(true);
 #ifndef USE_SEARCH_BUTTON
         tabChanged(1);
 #endif
 #ifdef USE_CONTACTS_COMBOBOX
         addressSelected(contactList->currentIndex());
 #else
         addressSelected(contactList->currentRow());
 #endif
     }
 }
 #ifndef USE_SEARCH_BUTTON
 void AddressFinder::tabChanged(int index)
 {
     QWidget* currentTab = tabWidget->currentWidget();
     QAction* action = 0;
     if(currentTab && !currentTab->actions().isEmpty())
         action = currentTab->actions().first();
     menuBar()->setDefaultAction(action);
     Q_UNUSED(index)
 }
 #endif
 void AddressFinder::setupUi()
 {
     setWindowTitle(tr("Keep In Touch"));
 #ifndef USE_SEARCH_BUTTON
     tabWidget = new QTabWidget(this);
     setCentralWidget(tabWidget);
     connect(tabWidget,SIGNAL(currentChanged(int)),this,SLOT(tabChanged(int)));
 #else
     QWidget* centralWidget = new QWidget(this);
     QScrollArea* scrollArea = new QScrollArea(this);
     scrollArea->setWidget(centralWidget);
     scrollArea->setWidgetResizable(true);
     setCentralWidget(scrollArea);
     QVBoxLayout* centralLayout = new QVBoxLayout(centralWidget);
 #endif
     QGroupBox *inputGroup = new QGroupBox(tr("Find addresses"));
     inputGroup->setAlignment(Qt::AlignLeft);
 #ifndef USE_SEARCH_BUTTON
     tabWidget->addTab(inputGroup,"Search");
 #else
     centralLayout->addWidget(inputGroup);
 #endif
     QGridLayout *filterLayout = new QGridLayout(inputGroup);
 #ifdef Q_WS_MAEMO_5
     
     int spacingHack = QFontMetrics(QFont()).height();
     filterLayout->setContentsMargins(0, spacingHack, 0, 0);
 #endif
     QLabel *includeLabel = new QLabel(tr("Contacted in the last"));
     filterLayout->addWidget(includeLabel, 0, 0);
     filterLayout->setAlignment(includeLabel, Qt::AlignRight);
     excludeCheckBox = new QCheckBox(tr("But not in the last"));
 #ifdef Q_WS_MAEMO_5
     
     excludeCheckBox->setText(excludeCheckBox->text() + "  ");
 #endif
     connect(excludeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(excludePeriodEnabled(int)));
     filterLayout->addWidget(excludeCheckBox, 1, 0);
     filterLayout->setAlignment(excludeCheckBox, Qt::AlignRight);
     includePeriod = new QComboBox;
     includePeriod->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
     includePeriod->addItem(tr("Year"));
     includePeriod->addItem(tr("9 Months"));
     includePeriod->addItem(tr("6 Months"));
     includePeriod->addItem(tr("3 Months"));
     includePeriod->addItem(tr("Month"));
     includePeriod->addItem(tr("Week"));
     connect(includePeriod, SIGNAL(currentIndexChanged(int)), this, SLOT(includePeriodChanged(int)));
     filterLayout->addWidget(includePeriod, 0, 1);
     excludePeriod = new QComboBox;
     excludePeriod->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
     filterLayout->addWidget(excludePeriod, 1, 1);
     excludePeriod->setEnabled(false);
 #ifdef USE_SEARCH_BUTTON
     searchButton = new QPushButton(tr("Search"));
     searchButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
     connect(searchButton, SIGNAL(clicked()), this, SLOT(searchMessages()), Qt::QueuedConnection);
     filterLayout->addWidget(searchButton, 2, 1);
 #endif
 #ifdef USE_CONTACTS_COMBOBOX
     contactList = new QComboBox(this);
     connect(contactList, SIGNAL(currentIndexChanged(int)), this, SLOT(addressSelected(int)));
 #else
     contactList = new QListWidget(this);
     connect(contactList, SIGNAL(currentRowChanged(int)), this, SLOT(addressSelected(int)));
 #endif
 #ifndef USE_SEARCH_BUTTON
     QWidget* resultsWidget = new QWidget(this);
     QVBoxLayout* resultsLayout = new QVBoxLayout(resultsWidget);
     tabWidget->addTab(resultsWidget,"Results");
 #else
     QVBoxLayout* resultsLayout = centralLayout;
 #endif
     QGroupBox *addressGroup = new QGroupBox(tr("Contacts"));
     addressGroup->setAlignment(Qt::AlignLeft);
     addressGroup->setLayout(new QVBoxLayout);
 #ifdef Q_WS_MAEMO_5
     addressGroup->layout()->setContentsMargins(0, spacingHack, 0, 0);
 #endif
     addressGroup->layout()->addWidget(contactList);
     resultsLayout->addWidget(addressGroup);
     QGroupBox *messageGroup = new QGroupBox(tr("Messages"));
     messageGroup->setAlignment(Qt::AlignLeft);
     QVBoxLayout *groupLayout = new QVBoxLayout;
 #ifdef Q_WS_MAEMO_5
     groupLayout->setContentsMargins(0, spacingHack, 0, 0);
 #endif
     messageCombo = new QComboBox;
     connect(messageCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(messageIndexChanged(int)));
     groupLayout->addWidget(messageCombo);
     showButton = new QPushButton(tr("Show..."));
     showButton->setEnabled(false);
     connect(showButton, SIGNAL(clicked()), this, SLOT(showMessage()));
     forwardButton = new QPushButton(tr("Forward..."));
     forwardButton->setEnabled(false);
     connect(forwardButton, SIGNAL(clicked()), this, SLOT(forwardMessage()));
     QHBoxLayout *buttonLayout = new QHBoxLayout;
     buttonLayout->addWidget(showButton);
     buttonLayout->addWidget(forwardButton);
     groupLayout->addLayout(buttonLayout);
     messageGroup->setLayout(groupLayout);
     resultsLayout->addWidget(messageGroup);
     searchAction = new QAction("Search",this);
     inputGroup->addAction(searchAction);
     connect(searchAction,SIGNAL(triggered()),this,SLOT(searchMessages()),Qt::QueuedConnection);
     QAction* quitAction = menuBar()->addAction("Quit");
     connect(quitAction,SIGNAL(triggered()),qApp,SLOT(quit()));
     includePeriodChanged(0);
 #ifndef USE_SEARCH_BUTTON
     tabChanged(0);
 #endif
     QWidgetList focusableWidgets;
     focusableWidgets << excludeCheckBox
                      << includePeriod
                      << excludePeriod
                      << contactList
                      << messageCombo
                      << showButton
 #ifndef USE_SEARCH_BUTTON
                      << tabWidget
 #else
                      << searchButton
                      << scrollArea
 #endif
                      << forwardButton;
   foreach(QWidget* w, focusableWidgets)
        w->setContextMenuPolicy(Qt::NoContextMenu);
     includePeriod->setFocus();
 }
 void AddressFinder::setSearchActionEnabled(bool val)
 {
     searchAction->setEnabled(val);
 #ifdef USE_SEARCH_BUTTON
     if (val)
         searchButton->setText(tr("Search"));
     else
         searchButton->setText(tr("Searching.."));
     searchButton->setEnabled(val);
 #endif
 }
 void AddressFinder::messageIndexChanged(int index)
 {
     bool messageSelected(index != -1);
     showButton->setEnabled(messageSelected);
     forwardButton->setEnabled(messageSelected);
 }
 void AddressFinder::showMessage()
 {
     int index = messageCombo->currentIndex();
     if (index != -1) {
         
         const QString &selectedAddress(addressList[
 #ifdef USE_CONTACTS_COMBOBOX
                 contactList->currentIndex()
 #else
                 contactList->currentRow()
 #endif
                 ]);
         
         QMessageId &messageId((addressMessages[selectedAddress])[index].second);
         service.show(messageId);
     }
 }
 void AddressFinder::forwardMessage()
 {
     int index = messageCombo->currentIndex();
     if (index != -1) {
         
         const QString &selectedAddress(addressList[
 #ifdef USE_CONTACTS_COMBOBOX
                 contactList->currentIndex()
 #else
                 contactList->currentRow()
 #endif
                 ]);
         
         QMessageId &messageId((addressMessages[selectedAddress])[index].second);
         QMessage original(messageId);
         
         QMessage fwd(original.createResponseMessage(QMessage::Forward));
         fwd.setTo(original.to());
         service.compose(fwd);
     }
 }