//==================================================================================================
// P r o g r a m                                                                          Interface
// S h o w _ d i r
// C o n s o l e
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library 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 Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides facilities to execute the program in console mode. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "program/show_dir/console.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guProgramShowDirConsole
#define guProgramShowDirConsole

// Headers //---------------------------------------------------------------------------------------
#include <bpp/calendar.hpp> /*INCLUDE*/

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef PROGRAM_SHOW_DIR_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  programShowDirConsole
#define private_area programShowDirConsole_private

namespace public_area  { /*NAMESPACE*/ using namespace standard; }
namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniProgramShowDirConsole
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area { class clFolderProcessingListII; }

// Functions Interface //---------------------------------------------------------------------------
namespace public_area  { function tyReturn run(tyCardinal,tcString []); }
namespace private_area {}

// Errors //----------------------------------------------------------------------------------------
namespace public_area { /*ERROR*/ extern_error erSyntax; /* Syntax error in the command line. */ }

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// F o l d e r P r o c e s s i n g L i s t I I  Interface //----------------------------------------
namespace private_area {
 class clFolderProcessingListII : public clFolderProcessing {
  //-----------------------------------------------------------------------------------------Private
  private_property tyString      atFormat;
  private_property tyBoolean     atCaseSensitive;
  private_property clString      atBlankSpace;
  private_property tyBoolean     atStored;
  private_property clOutStream & atStream;
  private_property tyBoolean     atDisplayed;

  private_property constructor clFolderProcessingListII(const clFolderProcessingListII &);
  private_property clFolderProcessingListII & operator = (const clFolderProcessingListII &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clFolderProcessingListII(tcString=nil,tyBoolean=true,tcString="",
                                                       clOutStream * =nil,tyBoolean=true);

  public_property virtual destructor clFolderProcessingListII(void);

  public_property void startFolder(ctString &);
  public_property void endFolder(ctString &);
  public_property void file(ctString &);
  public_property void unknown(ctString &);
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// F o l d e r P r o c e s s i n g L i s t I I  Inline //-------------------------------------------
namespace private_area {
 //---------------------------------------------------------------------------------------Destructor
 inline clFolderProcessingListII::~clFolderProcessingListII(void)
 { if (atFormat!=nil and not atCaseSensitive) { delete_array(atFormat); } }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// P r o g r a m                                                                     Implementation
// S h o w _ d i r
// C o n s o l e
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library 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 Library General Public License for more details (http://www.gnu.org).

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "program/show_dir/console.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define PROGRAM_SHOW_DIR_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/program/show_dir/console.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  programShowDirConsole
#define private_area programShowDirConsole_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Program/Show_dir/Console");

// Initialization //--------------------------------------------------------------------------------
#undef iniProgramShowDirConsole
static_constant(private_area::clInitializer,goInitializer);

// Errors //----------------------------------------------------------------------------------------
namespace public_area { static_error erSyntax; }

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------------Run
 /*FUNCTION*/
 /* Start function of the program. It deals with the commands the user gives through a command
    line and executes the appropriate functions. */
 function tyReturn run(tyCardinal agCounter,tcString agParameterS[]) {
  method_name("run");

  clString lcCommand;

  tyCardinal lcCounter = 1;

  environment_private::goProgramName = "S h o w   D i r";

  tcString lcFileName = "";
  tcString lcFolder   = ".";
  tcString lcFormat   = nil;

  tyBoolean lcCaseSensitive = false;
  tyBoolean lcDisplayed     = true;
  tyBoolean lcList          = false;
  tyBoolean lcRecursive     = false;
  tyBoolean lcStored        = false;

  clOutFile     lcFile;
  clOutStream * lcStream;

  try {
   if (agCounter==1) send_error(erSyntax);

   while (lcCounter<agCounter) {
    lcCommand=agParameterS[lcCounter];

    //---------------------------------------------------------------------------------------Context
    if (lcCommand=="+context") {
     environment::nextLine();
     environment::outContext();
    }

    //------------------------------------------------------------------------------------------Help
    else if (lcCommand=="+help") {
     environment::nextLine();
     environment::inform("-=-=- H E L P -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
     environment::out(" This program shows the content of a folder.",true,true);
     environment::nextLine();
     environment::out(" * Syntax: [options] [commands] [format string]",true,true);
     environment::nextLine();
     environment::out(" * Options:",true,true);
     environment::out("   -hide       = deactivates the display of the list.",true,true);
     environment::out("   -output <f> = stores the list into the file <f>.",true,true);
     environment::out("   -path <f>   = defines the folder to scan.",true,true);
     environment::out("                 Without this option, the current folder is scanned.",true,true);
     environment::out("   -recursive  = forces the scanning to be recursive.",true,true);
     environment::out("   -sensitive  = forces the scanning to be case sensitive.",true,true);
     environment::nextLine();
     environment::out(" * Commands:",true,true);
     environment::out("   +context = shows the context of the program's running.",true,true);
     environment::out("   +help    = shows this help.",true,true);
     environment::out("   +info    = shows information about the program.",true,true);
     environment::out("   +license = shows the license of the program.",true,true);
     environment::out("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-",true,true);
    }

    //------------------------------------------------------------------------------------------Info
    else if (lcCommand=="+info") {
     environment::nextLine();
     environment::outInformation();
    }

    //---------------------------------------------------------------------------------------License
    else if (lcCommand=="+license") {
     environment::nextLine();
     environment::outLicense();
    }

    //------------------------------------------------------------------------------------------Hide
    else if (lcCommand=="-hide") {
     lcDisplayed=false;
     lcList=true;
    }

    //----------------------------------------------------------------------------------------Output
    else if (lcCommand=="-output") {
     if (agCounter-lcCounter>1) {
      lcFileName=agParameterS[lcCounter+1];
      lcCounter+=1;
      lcStored=true;
      lcList=true;
     }
    }

    //-------------------------------------------------------------------------------------Recursive
    else if (lcCommand=="-recursive") {
     lcRecursive=true;
     lcList=true;
    }

    //-------------------------------------------------------------------------------------Sensitive
    else if (lcCommand=="-sensitive") {
     lcCaseSensitive=true;
     lcList=true;
    }

    //------------------------------------------------------------------------------------------Path
    else if (lcCommand=="-path") {
     if (agCounter-lcCounter>1) {
      lcFolder=agParameterS[lcCounter+1];
      lcCounter+=1;
      lcList=true;
     }
    }

    else {
     lcFormat=agParameterS[lcCounter];
     lcList=true;
    }

    lcCounter++;
   }

   if (lcList) {
    if (lcStored) {
     open(lcFile,lcFileName,ios::out|ios::trunc);
     if (lcFile.fail()) send_error(erFileWriting);

     lcStream=&lcFile;
    }
    else lcStream=nil;

    private_area::clFolderProcessingListII
    lcProcessing(lcFormat,lcCaseSensitive,"",lcStream,lcDisplayed);

    if (lcDisplayed) environment::nextLine();
    scanFolder(lcFolder,lcProcessing,lcRecursive);

    if (lcStored) {
     if (lcFile.fail()) send_error(erFileWriting);
     close(lcFile);
    }
   }
  }

  program_catch;
 }
}

namespace private_area {}

// F o l d e r P r o c e s s i n g L i s t  Implementation //---------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------Constructor
 property clFolderProcessingListII::
 clFolderProcessingListII(tcString agFormat,tyBoolean agCaseSensitive,tcString agBlankSpace,
                          clOutStream * agStream,tyBoolean agDisplayed)
 : atFormat(tyString(agFormat)),atCaseSensitive(agCaseSensitive),atBlankSpace(agBlankSpace),
   atStored(agStream!=nil),atStream(*agStream),atDisplayed(agDisplayed) {
  if (agFormat!=nil and not atCaseSensitive) {
   atFormat=new_array(tyCharacter,size(agFormat)+1);
   copy(atFormat,agFormat);
   lowerCase(atFormat);
  }
 }
 //--------------------------------------------------------------------------------------StartFolder
 property void clFolderProcessingListII::startFolder(ctString & agFullName) {
  private_area::clString lcPath;
  private_area::clString lcShortName;

  extractShortName(lcPath,lcShortName,agFullName);

  if (atDisplayed) {
   environment::out(atBlankSpace.data(),false,true);
   environment::out(lcShortName.data());
   environment::out(":",true);
  }

  if (atStored) atStream << atBlankSpace << lcShortName << ':' << end_line;;
  atBlankSpace+=" ";
 }
 //----------------------------------------------------------------------------------------EndFolder
 property void clFolderProcessingListII::endFolder(ctString &) {
  atBlankSpace=atBlankSpace.part(0,atBlankSpace.size()-1);
 }
 //---------------------------------------------------------------------------------------------File
 property void clFolderProcessingListII::file(ctString & agFullName) {
  private_area::clString lcBody;
  private_area::clString lcExtension;
  private_area::clString lcPath;
  private_area::clString lcShortName;
  tyInteger              lcSize;
  tyString               lcTempo;

  extractShortName(lcPath,lcShortName,agFullName);
  lcTempo=tyString(lcShortName.data());
  if (not atCaseSensitive) lowerCase(lcTempo);

  if (atFormat==nil or matched(lcTempo,atFormat)) {
   separateFileName(lcBody,lcExtension,lcShortName);
   lcSize=fileSize(agFullName.data());

   if (atDisplayed) {
    environment::out(atBlankSpace.data(),false,true);
    environment::out(lcShortName.data());
    environment::out(" [");
    environment::out(lcExtension.data());
    environment::out("] ");
    environment::out(lcSize);
    environment::out(" bytes",true);
   }

   if (atStored) {
    atStream << atBlankSpace << lcShortName << " [" << lcExtension << "] " << lcSize;
    atStream << " bytes" << end_line;
   }
  }
 }
 //------------------------------------------------------------------------------------------Unknown
 property void clFolderProcessingListII::unknown(ctString & agFullName) {
  private_area::clString lcPath;
  private_area::clString lcShortName;

  extractShortName(lcPath,lcShortName,agFullName);

  if (atDisplayed) {
   environment::out(atBlankSpace.data(),false,true);
   environment::out(lcShortName.data());
   environment::out(" ?",true);
  }

  if (atStored) atStream << atBlankSpace << lcShortName << " ?" << end_line;
 }
}

// I n i t i a l i z e r  Implementation //---------------------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------------Start
 property void clInitializer::start(void) {
  if (atCounter++ == 0) {
   try {
    #include <bpp/modules.hpp> /*NEED*/
    registerStop(this);
    environment::informInitialization(goModuleName);

    erSyntax.create("Show Dir - Use the '+help' parameter to get some help.");
   }

   initializer_catch;
  }
 }
 //---------------------------------------------------------------------------------------------Stop
 property void clInitializer::stop(void) {
  try {
   environment::informTermination(goModuleName);

   // ...
  }

  initializer_catch;
 }
}

// End //-------------------------------------------------------------------------------------------
}