/*
 *   kiosksync.cpp
 *
 *   Copyright (C) 2004 Waldo Bastian <bastian@kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License version 2 as
 *   published by the Free Software Foundation.
 *
 *   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 "kiosksync.h"

#include <qdir.h>
#include <qwidget.h>

#include <kdebug.h>
#include <klocale.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>

KioskSync::KioskSync( QWidget* parent, const char* name)
 : QObject(parent, name),
   m_parent(parent)
{
}

KioskSync::~KioskSync()
{
}

void
KioskSync::addDir(const QString &_src, const KURL &dest)
{
   QString src = _src;
   if (!src.endsWith("/"))
      src.append("/");
   
   m_syncDirs.append(SyncDir(src, dest));
}

bool
KioskSync::sync(bool incremental)
{
   m_incremental = incremental;
   m_timestamps = new KSimpleConfig(locateLocal("appdata", "profile-data"));

   bool canceled = false; 
 
   for(SyncDirList::ConstIterator it = m_syncDirs.begin();
       it != m_syncDirs.end(); ++it)
   {
      m_changedFiles.clear();
      m_changedDirs.clear();
      
      m_timestamps->setGroup((*it).src);

      if (!KioskRun::self()->createRemoteDirRecursive((*it).dest, true))
      {
         canceled = true;
         break;
      }
      
      scanChangedFiles((*it).src, QString::null);

      for(QStringList::ConstIterator it2 = m_changedDirs.begin();
          it2 != m_changedDirs.end(); ++it2)
      {
         KURL dest = (*it).dest;
         dest.setPath(dest.path(1) + *it2);
         if (!KioskRun::self()->createRemoteDir(dest))
         {
            canceled = true;
            break;
         }
      }

      if (canceled)
         break;

      for(QStringList::ConstIterator it2 = m_changedFiles.begin();
          it2 != m_changedFiles.end(); ++it2)
      {
         KURL dest = (*it).dest;
         dest.setPath(dest.path(1) + *it2);
         if (!syncFile((*it).src, *it2, dest))
         {
            canceled = true;
            break;
         }
      }
      if (canceled)
         break;
   }
   delete m_timestamps;
   m_changedFiles.clear();
   m_changedDirs.clear();
   
   return !canceled;
}

QStringList
KioskSync::listFiles()
{
   m_changedFiles.clear();
   m_changedDirs.clear();
   m_incremental = false;
   m_timestamps = 0;

   for(SyncDirList::ConstIterator it = m_syncDirs.begin();
       it != m_syncDirs.end(); ++it)
   {
      scanChangedFiles((*it).src, QString::null);
   }
   return m_changedFiles;
}

void
KioskSync::addChangedDir(const QString &dir)
{
   if (dir.isEmpty())
      return;

   if (m_changedDirs.contains(dir))
      return;

   int i = dir.findRev('/', -2);
   if (i != -1)
   {
       QString parentDir = dir.left(i+1);
       addChangedDir(parentDir);
   }

   kdDebug() << "KioskSync: Adding " << dir << endl;
   m_changedDirs.append(dir);
}

void
KioskSync::scanChangedFiles(const QString &_dir, const QString &prefix)
{
   kdDebug() << "KioskSync: Scanning " << _dir << endl;
   QDir dir(_dir);
   if (!dir.exists())
   {
       emit warning(i18n("Directory <b>%1</b> does not exist.").arg(_dir));
       return;
   }
   if (!dir.isReadable())
   {
       emit warning(i18n("Directory <b>%1</b> is not readable.").arg(_dir));
       return;
   }

   QStringList subDirs;
   const QFileInfoList *list = dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoSymLinks);

   bool dirtyDir = false;   
   QFileInfoListIterator it( *list );
   for ( QFileInfo *fi; (fi = it.current()) != 0; ++it)
   {
       if (fi->isDir())
       {
          QString subDir = fi->fileName();
          if ((subDir != ".") && (subDir != ".."))
             subDirs.append(subDir+"/");
          continue;
       }
 
       // TODO: Check file
       QString file = prefix + fi->fileName();
       QDateTime lastModified = fi->lastModified();
       if (!m_incremental || !m_timestamps->hasKey(file) || 
           (m_timestamps->readDateTimeEntry(file) != lastModified))
       {
          dirtyDir = true;
          m_changedFiles.append(file);
       }
   }
   if (dirtyDir)
      addChangedDir(prefix);
   
   for( QStringList::ConstIterator it = subDirs.begin();
        it != subDirs.end(); ++it)
   {
       QString subDir = *it;
       scanChangedFiles(_dir + subDir, prefix + subDir);
   }
}

bool
KioskSync::syncFile(const QString &prefix, const QString &file, const KURL &dest)
{
   kdDebug() << "KioskSync: Syncing [" << prefix << "]" << file << " --> " << dest.prettyURL() << endl;
   
   if (!KioskRun::self()->uploadRemote(prefix+file, dest))
       return false;
   
   QFileInfo fi(prefix+file);
   m_timestamps->writeEntry(file, fi.lastModified());
   return true;
}

#include "kiosksync.moc"
