#include "konsume.h"

#include <klineedit.h>
#include <kiconloader.h>
#include <kapplication.h>
#include <kfiledialog.h>
#include <kglobal.h>
#include <ktoolinvocation.h>
#include <kstandardguiitem.h>
#include <kstatusnotifieritem.h>

Konsume::Konsume(QWidget *parent) : QDialog(parent), m_eBay(this)
{
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    setupUi(this);

    // create tray icon
    KStatusNotifierItem *tray = new KStatusNotifierItem(this);
    tray->setIconByName("konsume");
    tray->setCategory(KStatusNotifierItem::ApplicationStatus);

    menuActions = new QMenu(this);
    menuActions->addAction(i18n("Open in Browser"), this, SLOT(slotOpenCurrentItemInBrowser()), Qt::CTRL + Qt::Key_O);
    menuActions->addAction(i18n("Remove from Watchlist"), this, SLOT(slotRemoveCurrentItemFromWatchList()), QKeySequence("Del"));

    m_list->setSortingEnabled(true);
    m_list->setRootIsDecorated(false);
    m_list->sortByColumn(3, Qt::AscendingOrder);
    m_list->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(m_list, SIGNAL(customContextMenuRequested(QPoint)), SLOT(slotCustomContextMenuRequested(QPoint)));

    m_progressBar->setVisible(false);

    m_alarms->setValidator(new QRegExpValidator(QRegExp("[0-9]+\\!{0,1}(,[0-9]+\\!{0,1})*"), this));

    // Update the auction-end countdown every second
    timerCountdown = new QTimer(this);
    connect(timerCountdown, SIGNAL(timeout()), SLOT(slotUpdateCountdown()));
    timerCountdown->setInterval(1000);
    timerCountdown->start();

    // Connect buttons
    connect(m_updateWatchlist, SIGNAL(clicked()), this, SLOT(slotGetWatchList()));
    connect(m_tokenGenerate, SIGNAL(clicked()), &m_eBay, SLOT(slotSendGetSessionID()));
    connect(m_tokenReset, SIGNAL(clicked()), &m_eBay, SLOT(slotSendRevokeToken()));

    // Connect eBay-class to our UI
    connect(&m_eBay, SIGNAL(logMessage(const QString)), m_logWindow, SLOT(append(const QString)));
    connect(&m_eBay, SIGNAL(authTokenChanged(const QString)), SLOT(slotAuthTokenChanged(const QString)));
    connect(&m_eBay, SIGNAL(receivedWatchList(const QList<Auction*>)), SLOT(slotLoadAuctions(const QList<Auction*>)));

    // Open an auction when its dblclicked
    connect(m_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), SLOT(slotOpenAuctionInBrowser(QTreeWidgetItem*)));

    initSiteIds();
    slotLoadSettings();

    // Update the watchlist from eBay according to the loaded settings
    timerUpdateWatchlist = new QTimer(this);
    connect(timerUpdateWatchlist, SIGNAL(timeout()), &m_eBay, SLOT(slotSendGetWatchList()));
    timerUpdateWatchlist->setInterval(m_updateWatchlistInterval->value() * 60 * 1000);
    timerUpdateWatchlist->start();

    // When fields change, save settings
    connect(m_eBaySiteId, SIGNAL(activated(int)), SLOT(slotSaveSettings()));
    connect(m_alarms, SIGNAL(editingFinished()), SLOT(slotSaveSettings()));
    connect(m_updateWatchlistInterval, SIGNAL(editingFinished()), SLOT(slotSaveSettings()));
    connect(m_translateEndTimes, SIGNAL(stateChanged(int)), SLOT(slotSaveSettings()));

    show();
}

Konsume::~Konsume()
{
  m_list->clear();
}

void Konsume::slotGetWatchList()
{
  m_progressBar->setVisible(true);
  m_eBay.slotSendGetWatchList();
}

void Konsume::slotOpenAuctionInBrowser(QTreeWidgetItem *auction)
{
  qDebug() << __FILE__ << __FUNCTION__ << "opening auction" << ((Auction*)auction)->itemId() << "in browser:" << (((Auction*)auction)->url());
  QDesktopServices::openUrl(((Auction*)auction)->url());
}

void Konsume::initSiteIds()
{
  siteIds["Australia"] = 15;
  siteIds["Austria"] = 16;
  siteIds["Belgium (Dutch)"] = 123;
  siteIds["Belgium (French)"] = 23;
  siteIds["Canada"] = 2;
  siteIds["Canada (French)"] = 210;
  siteIds["France"] = 71;
  siteIds["Germany"] = 77;
  siteIds["Hong Kong"] = 201;
  siteIds["Ireland"] = 205;
  siteIds["India"] = 203;
  siteIds["Italy"] = 101;
  siteIds["Malaysia"] = 207;
  siteIds["Netherlands"] = 146;
  siteIds["Philippines"] = 211;
  siteIds["Poland"] = 212;
  siteIds["Singapore"] = 216;
  siteIds["Spain"] = 186;
  siteIds["Switzerland"] = 193;
  siteIds["United Kingdom"] = 3;
  siteIds["United States"] = 0;
  siteIds["US eBay Motors"] = 100;

  QMapIterator<QString, int> i(siteIds);
  while(i.hasNext())
  {
    i.next();
    m_eBaySiteId->addItem(i.key(), i.value());
  }
}

void Konsume::slotQuit()
{
  qDebug() << __FILE__ << __FUNCTION__;

  // We're shutting down and should remove leftover notifications.
  // For that, we need to delete all existing auctions by simply
  // clear()ing the listWidget
  m_list->clear();
  
  slotSaveSettings();
}

void Konsume::slotUpdateCountdown()
{
  m_list->update();
  //qDebug() << "Konsume::slotUpdateCountdown()";
  QTreeWidgetItemIterator it(m_list);
  while (*it)
  {
    Auction *auction = (Auction*)*it;
    auction->update(m_translateEndTimes->isChecked());
    ++it;
  }

//   static int columnsAdjusted = 0;
//   if(columnsAdjusted < 2)
//   {
//     for(int i = 0; i < m_list->columnCount(); ++i)
//       m_list->resizeColumnToContents(i);
//     columnsAdjusted++;
//   }
}

void Konsume::slotAuthTokenChanged(const QString authToken)
{
  if(authToken.isEmpty())
  {
    m_tokenGenerate->setEnabled(true);
    m_tokenReset->setEnabled(false);
    m_tokenStatus->setText("<b>absent</b>");
  }
  else
  {
    m_tokenGenerate->setEnabled(false);
    m_tokenReset->setEnabled(true);
    m_tokenStatus->setText("<b>present</b>");
  }

  slotSaveSettings();
}


void Konsume::slotLoadSettings()
{
  qDebug() << __FILE__ << __FUNCTION__;
  
  // Load settings of Setting-UI
  KConfigGroup settings = KGlobal::config().data()->group("Settings");
  m_translateEndTimes->setChecked(settings.readEntry("translateEndTimes", true));
  m_alarms->setText(settings.readEntry("alarms", "30,15,5!,4,3,2"));
  m_updateWatchlistInterval->setValue(settings.readEntry("updateWatchlistInterval", 10));
  
  // Load Settings for eBay-class
  settings = KGlobal::config().data()->group("eBayAPI");
  const int siteId = settings.readEntry("siteid", 0);
  m_eBay.setSiteId(siteId);

  // To which index do we have to set the combobox?
  QMapIterator<QString, int> i(siteIds);
  int position = 0;
  while(i.hasNext())
  {
    i.next();
    if(i.value() == siteId)
    {
      m_eBaySiteId->setCurrentIndex(position);
      continue;
    }
    position++;
  }

  // Setting the authToken causes eBay to emit authTokenChanged(), which is connected
  // to saveSettings(), which calls eBay::getWatchList() to (re)load auctions. What a
  // perfect way to start up :)
  m_eBay.setAuthToken(settings.readEntry("authtoken", ""));
}

void Konsume::slotSaveSettings()
{
  qDebug() << __FILE__ << __FUNCTION__;
  
  KConfigGroup settings = KGlobal::config().data()->group("Settings");
  settings.writeEntry("translateEndTimes", m_translateEndTimes->isChecked());
  settings.writeEntry("alarms", m_alarms->text());
  settings.writeEntry("updateWatchlistInterval", m_updateWatchlistInterval->value());
  settings.sync();

  settings = KGlobal::config().data()->group("eBayAPI");
  settings.writeEntry("authtoken", m_eBay.authToken());
  settings.writeEntry("siteid", siteIds.value(m_eBaySiteId->currentText()));
  settings.sync();

  // Settings were changed, possibly also alarms. To take
  // effect immediately, we need to reload the auctions.
  slotGetWatchList();
}

void Konsume::slotLoadAuctions(const QList<Auction*> auctions)
{
  m_progressBar->setVisible(false);

  qDebug() << __FILE__ << __FUNCTION__ << "deleting" << m_list->topLevelItemCount() << "old auctions";
  // This will also *delete* the auctions.
  m_list->clear();

  qDebug() << __FILE__ << __FUNCTION__ << "loading" << auctions.length() << "new auctions";

  for(int i = 0; i < auctions.size(); ++i)
  {
    m_list->addTopLevelItem((QTreeWidgetItem*)auctions.at(i));

    connect(auctions.at(i), SIGNAL(openBrowserForAlarm(QTreeWidgetItem*)), SLOT(slotOpenAuctionInBrowser(QTreeWidgetItem*)));
  }

  slotUpdateCountdown();
  slotUpdateCountdown();
  slotUpdateCountdown();
  slotUpdateCountdown();
  slotUpdateCountdown();
  slotUpdateCountdown();
  slotUpdateCountdown();
  slotUpdateCountdown();

  for(int i = 0; i < m_list->columnCount(); ++i)
    m_list->resizeColumnToContents(i);
}

void Konsume::slotCustomContextMenuRequested(const QPoint &point)
{
  menuActions->exec(m_list->mapToGlobal(point));
}

void Konsume::slotOpenCurrentItemInBrowser()
{
  slotOpenAuctionInBrowser(m_list->currentItem());
}

void Konsume::slotRemoveCurrentItemFromWatchList()
{
  if(KMessageBox::Yes == KMessageBox::questionYesNo(this, i18n("Are you sure you want to remove this item from your watchlist?"), i18n("Remove item from watchlist")))
  {
    m_eBay.slotSendRemoveFromWatchList(((Auction*)m_list->currentItem())->itemId());
    delete m_list->takeTopLevelItem(m_list->indexOfTopLevelItem(m_list->currentItem()));
  }
}
