/*! @file

    @id $Id$
*/
//       1         2         3         4         5         6         7         8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890

#include <qbrowserlib/log.hxx>
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QTimer>
#include <QtCore/QDateTime>

#include <cassert>

//! Store string lists.
/** Abstract storage interface to string lists, such as bookmarks. */
class Storage: public QObject {
    Q_OBJECT;
  Q_SIGNALS:
    //! Emitted if file content has changed.
    void changed();
  public:
    Storage() {
      TRC;
    }
    ~Storage() {
      TRC;
    }
    /*! @return true if readable or writable */
    bool valid() {
      return readable() || writeable();
    }
    /*! @return true if valid */
    operator bool() {
      return valid();
    }
    /*! @return name of the storage, e.g. filename */
    virtual QString name() = 0;
    /*! @return true if storage object already exists */
    virtual bool readable() = 0;
    /*! @return true if storage object exists or could be created */
    virtual bool writeable() = 0;
    /*! @return storage content as string list */
    virtual QStringList read() = 0;
    //! Writes storage content from string list.
    virtual bool write(const QStringList& out) = 0;
  public Q_SLOTS:
    void emitChanged() {
      TRC;
      changed();
    }
};

//! Implement @ref Storage for files.
class FileStorage: public Storage {
    Q_OBJECT;
  public:
    /*! @param file full path to storage file */
    FileStorage(QString file, int msec=1000): _file(file) {
      TRC; LOG<<"file: "<<file;
      assert(connect(&_timer, SIGNAL(timeout()), SLOT(check())));
      _timer.setInterval(msec);
      _timer.start();
    }
    QString name() {
      return _file.fileName();
    }
    bool readable() {
      return QFileInfo(_file).exists();
    }
    bool writeable() {
      return readable() ||
        (!_file.fileName().isEmpty() &&
         QFileInfo(_file).absoluteDir().exists());
    }
    QStringList read() {
      TRC;
      QStringList res;
      if (readable()) {
        if (_file.open(QIODevice::ReadOnly))
          res=QString::fromUtf8(_file.readAll()).split("\n");
        _file.close();
      }
      return res;
    }
    bool write(const QStringList& out) {
      TRC;
      bool res(false);
      if (writeable()) {
        if (_file.open(QIODevice::WriteOnly))
          if (_file.write(out.join("\n").toUtf8())>=0) res=true;
        _file.close();
      }
      return res;
    }
  private Q_SLOTS:
    void check() {
      if (_modified!=QFileInfo(_file).lastModified()) {
        TRC;
        _modified = QFileInfo(_file).lastModified();
        LOG<<"file has been modified"<<_modified.toString();
        emitChanged();
      }
    }
  private:
    QFile _file;
    QDateTime _modified;
    QTimer _timer;
};
