/***************************************************************************
    smb4kmounter_p  -  This is a private helper class for Smb4KMounter.
                             -------------------
    begin                : Do Jul 19 2007
    copyright            : (C) 2007 by Alexander Reinholdt
    email                : dustpuppy@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *   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., 59 Temple Place, Suite 330, Boston,   *
 *   MA  02111-1307 USA                                                    *
 ***************************************************************************/

#ifndef SMB4KMOUNTER_P_H
#define SMB4KMOUNTER_P_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

// Qt includes
#include <QThread>
#include <QString>

// KDE includes
#include <kdebug.h>

// system includes
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef __FreeBSD__
#include <sys/statfs.h>
#include <unistd.h>
#else
#include <sys/param.h>
#include <sys/mount.h>
#endif
#include <errno.h>

// application specific includes
#include "smb4kshare.h"


class Smb4KMounterPrivate
{
  public:
    Smb4KMounterPrivate();
    ~Smb4KMounterPrivate();
    int timerTicks;

    class Thread : public QThread
    {
      public:
        Thread() : QThread(), m_share( NULL )
        {
          setTerminationEnabled( true );
        }

        ~Thread() {}

        void setShare( Smb4KShare *share ) { m_share = share; }

        virtual void run()
        {
          if ( m_share->isEmpty() )
          {
            kFatal() << "Smb4KMounterPrivate::Thread: No valid share object specified" << endl;
          }

          struct statvfs vfs;

          if ( statvfs( m_share->canonicalPath(), &vfs ) == -1 )
          {
            m_share->setInaccessible( true );
            m_share->setFreeDiskSpace( -1 );
            m_share->setTotalDiskSpace( -1 );
          }
          else
          {
            m_share->setInaccessible( false );

            double kB_block = (double)(vfs.f_bsize / 1000);
            double total = (double)(vfs.f_blocks*kB_block);
            double free = (double)(vfs.f_bfree*kB_block);

            m_share->setFreeDiskSpace( free );
            m_share->setTotalDiskSpace( total );
          }

          // Determine the file system. Expect under Solaris, we need
          // to use statfs for that.
          struct statfs fs;

          if ( statfs( m_share->canonicalPath(), &fs ) == -1 )
          {
            m_share->setFileSystem( Smb4KShare::Unknown );
          }
          else
          {
#ifndef __FreeBSD__
            if ( (uint)fs.f_type == 0xFF534D42 )
            {
              m_share->setFileSystem( Smb4KShare::CIFS );
            }
            else if ( (uint)fs.f_type == 0x517B )
            {
              m_share->setFileSystem( Smb4KShare::SMBFS );
            }
            else
            {
              m_share->setFileSystem( Smb4KShare::Unknown );
            }
#else
            // FIXME: Can we also use f_type??
            if ( !strncmp( fs.f_fstypename, "smbfs", strlen( fs.f_fstypename ) ) )
            {
              m_share->setFileSystem( Smb4KShare::SMBFS );
            }
            else
            {
              m_share->setFileSystem( Smb4KShare::Unknown );
            }
#endif
          }

          // Determine the owner and the group of the share if
          // necessary.
          if ( !m_share->uidIsSet() || !m_share->gidIsSet() )
          {
            struct stat buf;

            if ( lstat( m_share->canonicalPath(), &buf ) == -1 )
            {
              m_share->setUID( (uid_t)-1 );
              m_share->setGID( (gid_t)-1 );
            }
            else
            {
              m_share->setUID( buf.st_uid );
              m_share->setGID( buf.st_gid );
            }
          }
          else
          {
            // Do nothing
          }
        }

      private:
        Smb4KShare *m_share;
    };

    Thread thread;
    void clearData();
    void setShare( const Smb4KShare &share );
    Smb4KShare *share() { return &m_share; }

  private:
    Smb4KShare m_share;
};


class Smb4KMounterQueueContainer
{
  public:
    Smb4KMounterQueueContainer( int todo, const Smb4KShare &share );
    Smb4KMounterQueueContainer( int todo, const Smb4KShare &share, bool force, bool no_message );
    Smb4KMounterQueueContainer( int todo );
    ~Smb4KMounterQueueContainer();
    int todo() { return m_todo; }
    bool forceUnmount() { return m_force; }
    bool noMessage() { return m_no_message; }
    const Smb4KShare &share() const { return m_share; }

  private:
    int m_todo;
    Smb4KShare m_share;
    bool m_force;
    bool m_no_message;
};

#endif
