/* hw_volume_manager.hh
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2009-2023 Ralf Hoffmann.
 * You can contact me at: ralf@boomerangsworld.de
 *   or http://www.boomerangsworld.de/worker
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef HW_VOLUME_MANAGER_HH
#define HW_VOLUME_MANAGER_HH

#include "wdefines.h"
#include <string>
#include <list>
#include <set>

//TODO put includes into wdefines?
#ifdef HAVE_HAL_DBUS
#include <hal/libhal.h>
#endif

#if defined(HAVE_HAL_DBUS) or defined(HAVE_DBUS)
#include <dbus/dbus.h>
#endif

#include "fstabmounttable.hh"
#include "mtabmounttable.hh"

class HWVolume;

class HWVolumeManager
{
public:
    HWVolumeManager( const std::string &fstab_location = HW_VM_FSTAB,
                     const std::string &mtab_location = HW_VM_MTAB );
    ~HWVolumeManager();
    HWVolumeManager( const HWVolumeManager &other );
    HWVolumeManager &operator=( const HWVolumeManager &other );
    
    std::list<HWVolume> getVolumes();
    int mount( HWVolume &vol, std::string &error_return );
    int umount( HWVolume &vol, std::string &error_return );
    int eject( HWVolume &vol, std::string &error_return );
    int closeTray( HWVolume &vol, std::string &error_return );

    void update( HWVolume &vol );
    std::list<HWVolume> getNewVolumes( bool store_new = true );
    std::list<HWVolume> filterUniqueDevices( const std::list<HWVolume> &l ) const;

    void setMountCommand( const std::string &cmd );
    void setUnmountCommand( const std::string &cmd );
    void setPartitionFile( const std::string &file );
    void setFStabFile( const std::string &file );
    void setMtabFile( const std::string &file );
    void setEjectCommand( const std::string &cmd );
    void setCloseTrayCommand( const std::string &cmd );

    std::list<HWVolume> getEjectableDevices();

    std::string getDescription( const HWVolume &vol );

    bool getUDisksAvailable() const;
    bool getUDisks2Available() const;

    bool setPreferredUDisksVersion( int version );

    int retrySystemConnection();
    bool systemConnectionFailed() const;
private:
#ifdef HAVE_HAL_DBUS
    DBusConnection *m_dbus_conn;
    LibHalContext *m_hal_ctx;
#elif defined(HAVE_DBUS)
    DBusConnection *m_dbus_conn;
#endif
    bool m_udisks_available;
    bool m_udisks2_available;
    bool m_initial_connect_tried = false;
    bool m_dbus_unavailable = false;

    std::list< std::string > m_avail_parts;
    std::set< std::string > m_known_devices;
    FStabMountTable m_fstab_table;
    MtabMountTable m_mtab_table;
    std::string m_mount_command, m_unmount_command;
    std::string m_partition_file;
    std::string m_eject_command, m_closetray_command;

    int m_preferred_udisks_version;

    std::list< std::string > getAvailablePartitions();
    bool isAvailablePartition( const std::string &dev,
                               const std::list< std::string > &l );
    bool isSameDevice( const std::string &dev1,
                       const std::string &dev2 );
    bool isDevice( const std::string &dev );

    bool getBoolProperty( const std::string &udi,
                          const std::string &property );
    bool getBoolPropertyUDisks2( const std::string &path,
                                 const std::string &interface,
                                 const std::string &property );

    std::string getStringProperty( const std::string &udi,
                                   const std::string &property );
    std::string getStringPropertyUDisks2( const std::string &udi,
                                          const std::string &interface,
                                          const std::string &property );
    std::string getByteArrayPropertyUDisks2( const std::string &udi,
                                             const std::string &interface,
                                             const std::string &property );

    std::list< std::string > getStrlistProperty( const std::string &udi,
                                                 const std::string &property );
    std::list< std::string > getByteArrayListPropertyUDisks2( const std::string &udi,
                                                              const std::string &interface,
                                                              const std::string &property );

    loff_t getUint64Property( const std::string &udi,
                              const std::string &property );
    loff_t getUint64PropertyUDisks2( const std::string &udi,
                                     const std::string &interface,
                                     const std::string &property );

    int dbusMount( HWVolume &vol, std::string &error_return );
    int cmdMount( HWVolume &vol, std::string &error_return );
    int dbusUnmount( HWVolume &vol, std::string &error_return );
    int cmdUnmount( HWVolume &vol, std::string &error_return );
    int dbusEject( HWVolume &vol, std::string &error_return );
    int cmdEject( HWVolume &vol, std::string &error_return );
    int dbusCloseTray( HWVolume &vol, std::string &error_return );
    int cmdCloseTray( HWVolume &vol, std::string &error_return );

    int HALconnectionInit();
    int HALconnectionFini();
    bool HALisConnected();
    int HALreconnect();
};

#endif
