/***************************************************************************
    smb4kscanner.h  -  The network scan core class of Smb4K.
                             -------------------
    begin                : Sam Mai 31 2003
    copyright            : (C) 2003-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., 51 Franklin Street, Fifth Floor, Boston,   *
 *   MA  02110-1301 USA                                                    *
 ***************************************************************************/

#ifndef SMB4KSCANNER_H
#define SMB4KSCANNER_H

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

// TQt includes
#include <tqobject.h>
#include <tqstringlist.h>
#include <tqptrqueue.h>

// KDE includes
#include <kprocess.h>

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

// forward declarations
class Smb4KScannerPrivate;
class Smb4KWorkgroupItem;
class Smb4KHostItem;
class Smb4KShareItem;


/**
 * This is the core class, that communicates with the network. All look-up
 * stuff is done here.
 *
 * @author Alexander Reinholdt <dustpuppy@mail.berlios.de>
 */

class Smb4KScanner : public TQObject
{
  Q_OBJECT
  

  public:
    /**
     * The constructor.
     *
     * @param workgroups      A list of Smb4KWorkgroupItem items which will be filled by the scanner
     *                        with the list of available workgroups. If a NULL pointer is passed, a
     *                        private list will be created which cannot be accessed from outside.
     *
     * @param hosts           A list of Smb4KHostItem items which will be filled by the scanner.
     *                        with the list of available hosts. If a NULL pointer is passed, a
     *                        private list will be created which cannot be accessed from outside.
     *
     * @param parent          The parent of this class.
     *
     * @param name            The name of this class.
     */
    Smb4KScanner( TQValueList<Smb4KWorkgroupItem *> *workgroups = 0,
                  TQValueList<Smb4KHostItem *> *hosts = 0,
                  TQObject *parent = 0,
                  const char *name = 0 );

    /**
     * The destructor.
     */
    ~Smb4KScanner();

    /**
     * Initiates a network scan.
     *
     * Please not that after having invoked this function, the list of workgroups
     * as well as the list of known hosts will be cleared and refilled. Thus, all
     * known hosts except the current workgroup master browsers will have been
     * vanished.
     */
    void rescan();

    /**
     * Aborts the network scan.
     */
    void abort();

    /**
     * Reads the options.
     */
    void readOptions();

    /**
     * Scan for the shares on a selected host.
     *
     * @param workgroup       The workgroup of the host you want to scan.
     *
     * @param host            The host you want to scan.
     *
     * @param ip              The IP address of the host.
     *
     * @param protocol        With this argument you can force a special protocol
     *                        the net command has to use. Normally, you do not have
     *                        to set here anything.
     */
    void getShares( const TQString &workgroup,
                    const TQString &host,
                    const TQString &ip,
                    const TQString &protocol = TQString() );

    /**
     * Scans for workgroup members.
     *
     * @param workgroup       The workgroup of the master browser that should be scanned.
     *
     * @param master          The name of the master browser.
     *
     * @param ip              The IP address of the master browser.
     */
    void getWorkgroupMembers( const TQString &workgroup,
                              const TQString &master,
                              const TQString &ip );

    /**
     * Get more info about a share (i.e. server and OS string, etc.).
     *
     * @param workgroup       The workgroup of the host
     *
     * @param host            The host's name
     *
     * @param ip              The host's IP address
     */
    void getInfo( const TQString &workgroup,
                  const TQString &host,
                  const TQString &ip );

    /**
     * Starts the search for a host that matches @p string. If the host is already
     * in the list of known hosts, this function immediately emits the searchResult()
     * signal with the Smb4KHostItem representing the host. If this is not the case,
     * a search process is started.
     *
     * @param string          The user supplied search string.
     */
    void search( const TQString &string );

    /**
     * This function returns an Smb4KWorkgroupItem, if the the workgroup
     * exists in the list, or NULL, if it does not.
     *
     * @param workgroup       The name of the workgroup
     */
    Smb4KWorkgroupItem *getWorkgroup( const TQString &workgroup );

    /**
     * This function reports if the scanner is running or not.
     *
     * @returns             TRUE if the scanner is running and FALSE otherwise.
     */
    bool isRunning() { return m_working; }

    /**
     * This function returns the specified host item, or NULL, if this host was not found.
     * The name of the host is mandatory. The workgroup may be empty, but should be given,
     * because this will speed up the search process.
     *
     * @param name          The name of the host
     *
     * @param workgroup     The workgroup of the host item
     *
     * @returns             A host item
     */
    Smb4KHostItem *getHost( const TQString &name,
                            const TQString &workgroup = TQString() );

    /**
     * This function inserts a @p host into the list of known servers. If it belongs to
     * a workgroup that was not known until now, a new Smb4KWorkgroupItem item is also
     * created and added to the list of known workgroups. @p host is then marked as
     * pseudo master browser. On success, the this function emits the hostAdded() and
     * hostListChanged() signals. If the host is already in the known, nothing is done.
     *
     * @param host          The host that should be inserted
     */
    void insertHost( Smb4KHostItem *host );

    /**
     * This function initializes the network scan It just executes the rescan() function,
     * so you can also use that instead.
     */
    void init();

  signals:
    /**
     * This signal emits the run state.
     *
     * @param state         The so-called run state. There are several defined
     *                      in the smb4kdefs.h header file.
     */
    void state( int state );

    /**
     * This signal is emitted, when the workgroup list has been updated.
     *
     * @param list          The list of workgroups in the network neighborhood.
     */
    void workgroups( const TQValueList<Smb4KWorkgroupItem *> &list );

    /**
     * Emits the list of workgroup members.
     *
     * @param workgroup     The workgroup in which the members are located
     *
     * @param list          The list of workgroup members.
     */
    void members( const TQString &workgroup, const TQValueList<Smb4KHostItem *> &list );

    /**
     * Emits the list of shares.
     *
     * @param host          The host that carries the shares
     *
     * @param list          The list of shares
     */
    void shares( const TQString &host, const TQValueList<Smb4KShareItem *> &list );

    /**
     * This signal provides info about a certain host. It passes the server
     * and the OS string.
     */
    void info( Smb4KHostItem *host );

    /**
     * Is emitted, when the results of a network search are to be passed.
     */
    void searchResult( Smb4KHostItem *host );

    /**
     * This signal emits the host item for which an IP address has
     * been found.
     *
     * @param host          The host item with the new IP address
     */
    void ipAddress( Smb4KHostItem *host );

    /**
     * This signal is emitted when the list of hosts is changed.
     */
    void hostListChanged();

    /**
     * This signal is emitted if a request could not be processed
     * successfully.
     */
    void failed();

    /**
     * This signal is emitted when a host has been added to the list of known
     * hosts via the addHost() function.
     *
     * @param host          The Smb4KHostItem that represents the host that
     *                      was added.
     */
    void hostAdded( Smb4KHostItem *host );

  protected:
    /**
     * Starts the process.
     *
     * @param state         The state
     */
    void startProcess( int state );

    /**
     * Is called, when the main process ends.
     */
    void endProcess();

    /**
     * Processes the output of the network group scan.
     */
    void processWorkgroups();

    /**
     * Processes the list of workgroup members retrieved by
     * scanning the workgroup master browser.
     */
    void processWorkgroupMembers();

    /**
     * Processes the output of the host scan.
     */
    void processShares();

    /**
     * Processes the output of the scan for the OS and Server
     * string.
     */
    void processInfo();

    /**
     * Processes the output of a search request.
     */
    void processSearch();

    /**
     * Process the data from the IP range scan.
     */
    void processIPScan();

    /**
     * Reimplemented from TQObject
     */
    void timerEvent( TQTimerEvent *e );

  protected slots:
    /**
     * Is called, if something is received on stdout from the main process.
     *
     * @param proc          The process
     *
     * @param buf           The buffer
     *
     * @param len           The length of the buffer
     */
    void slotReceivedStdout( TDEProcess *proc,
                             char *buf,
                             int len );

    /**
     * Is called, when the TDEProcess exited.
     *
     * @param proc          The process that exited
     */
    void slotProcessExited( TDEProcess *proc );

    /**
     * Is called, if something is received on stderr from the main process.
     *
     * @param proc          The process
     *
     * @param buf           The buffer
     *
     * @param len           The length of the buffer
     */
    void slotReceivedStderr( TDEProcess *proc,
                             char *buf,
                             int len );

    /**
     * Is called when the scan for IP addresses produced output on stdout.
     *
     * @param proc          The process
     *
     * @param buf           The buffer
     *
     * @param len           The length of the buffer
     */
    void slotReceivedIPAddresses( TDEProcess *proc,
                                  char *buf,
                                  int len );

    /**
     * Is called, when the TDEProcess exited.
     *
     * @param proc          The process that exited
     */
    void slotIPAddressProcessExited( TDEProcess *proc );


  private:
    /**
     * Initiates the (re-)scan of the network to retrieve the initial
     * browse list.
     */
    void scanNetwork();

    /**
     * Scans the group master for the group members.
     */
    void scanForWorkgroupMembers( const TQString &workgroup,
                                  const TQString &master,
                                  const TQString &ip );

    /**
     * Scans the chosen host for its shares. This is the private part
     * of @see Smb4KScanner::getShares().
     */
    void scanForShares( const TQString &workgroup,
                        const TQString &host,
                        const TQString &ip,
                        const TQString &protocol );

    /**
     * Scans a given host for its OS and Server string.
     */
    void scanForInfo( const TQString &workgroup,
                      const TQString &host,
                      const TQString &ip );

    /**
     * Searches for a given host.
     */
    void searchForHost( const TQString &host );

    /**
     * This function initializes the lookup of IP addresses.
     */
    void lookupIPAddresses();

    /**
     * This function takes an Smb4KWorkgroupItem and appends it to the list,
     * if the represented workgroup isn't already in it.
     */
    void appendWorkgroup( Smb4KWorkgroupItem *item );

    /**
     * Internal enumeration.
     */
    enum TODO{ Workgroups, QueryHost, IPScan, Hosts, Shares, Info, Search, Init, Idle };

    /**
     * The main TDEProcess object.
     */
    TDEProcess *m_proc;

    /**
     * The buffer for the main process.
     */
    TQString m_buffer;

    /**
     * This queue stores the incoming requests until they are processed.
     */
    TQPtrQueue<TQString> m_queue;

    /**
     * Is set to true, if the scanner is running.
     */
    bool m_working;

    /**
     * The list of workgroups including the master browser and their
     * IP addresses.
     */
    TQValueList<Smb4KWorkgroupItem *> *m_workgroups_list;

    /**
     * This list contains all hosts, that are found by the scanner and
     * that are currently active.
     */
    TQValueList<Smb4KHostItem *> *m_hosts_list;

    /**
     * The internal state of the main process. Do not mix this up with
     * the state that's emitted to notify the application about changes.
     */
    int m_state;

    /**
     * This is the pointer to the private helper class.
     */
    Smb4KScannerPrivate *m_priv;

    /**
     * The timer id
     */
    int m_timer_id;
};
#endif
