/**
 * \file BGDNetDrive.cpp
 * \brief Реализация классов NetworkDrive и NetworkDrives.
 */

#include "BGDNetPch.h"

#include "BGDNetDrive.h"

#include <ctype.h>
#include <nwdpath.h>
#include "BGDNetPath.h"
#include "BGDNetServer.h"
#include "BGDNetVolume.h"
#include "BGDNetDirectory.h"

#ifdef BGDNET_USE_MFC
# ifdef _DEBUG
#   define new DEBUG_NEW
#   undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
# endif
#endif

namespace BGDNet
{

NetworkDrive::NetworkDrive( char drv ) :
  m_drvLetter(toupper(drv)),
  m_pSrv(0),
  m_pVol(0),
  m_pDir(0)
{
  getMappedDir();
}

NetworkDrive::~NetworkDrive( void )
{
  if (m_pDir)
    delete m_pDir;
  if (m_pVol)
    delete m_pVol;
  if (m_pSrv)
    delete m_pSrv;
}

char NetworkDrive::drvLetter( void ) const
{
  return m_drvLetter;
}

Directory* NetworkDrive::mappedDir( void )
{
  return m_pDir;
}

const Directory* NetworkDrive::mappedDir( void ) const
{
  return m_pDir;
}

void NetworkDrive::getMappedDir( void )
{
  const nuint16 letter = drvLetter() - 'A' + 1;
  nuint16 status;
  nstr8 rootPath[256];
  NWCCODE err = NWGetDriveStatus(
    letter,
    NW_FORMAT_SERVER_VOLUME,
    &status,
    0,
    rootPath,
    0,
    0);
  if (SUCCESS != err)
    throw Exception(err);
  if (NW_NETWARE_DRIVE & status)
  {
    try
    {
      // Перед использованием необходимо преобразовать полученный путь
      // в OEM-кодировку!
      char oemPath[256];
      CharToOem(rootPath, oemPath);
      Path p(oemPath, NW_NS_LONG);
      m_pSrv = new Server(p.srv());
      m_pVol = new Volume(m_pSrv, p.vol());
      nuint8 ns = m_pVol->supportsLongNames() ? NW_NS_LONG : NW_NS_DOS;
      m_pDir = new Directory(m_pVol, Path(p.path(), ns));
    }
    catch (...)
    {
      if (m_pDir)
        delete m_pDir;
      if (m_pVol)
        delete m_pVol;
      if (m_pSrv)
        delete m_pSrv;
      throw;
    }
  }
}




NetworkDrives::NetworkDrives( void )
  throw(Exception)
{
  // Получаем номер первого сетевого диска:
  nuint16 firstDrive;
  NWCCODE err = NWGetFirstDrive(&firstDrive);
  if (SUCCESS != err)
    throw Exception(err);

  // Проходим по всем дискам и проверяем их доступность:
  for (char drvLetter = 'A' + firstDrive - 1; drvLetter <= 'Z'; ++drvLetter)
  {
    SharePtr<NetworkDrive> pDrv = new NetworkDrive(drvLetter);
    if (pDrv->mappedDir())
      m_drives.add(pDrv); // диск доступен, добавляем объект в коллекцию.
  }
}

int NetworkDrives::count( void ) const
{
  return m_drives.size();
}

NetworkDrive* NetworkDrives::operator []( int n )
{
  return m_drives[n];
}

const NetworkDrive* NetworkDrives::operator []( int n ) const
{
  return m_drives[n];
}

} // namespace BGDNet
