// ----------------------------------------------------------------------------
//   Input.h (created on Tue Aug 23 01:08:35 BRT 2005)
// 
//   Genetic Algorithm File Fitter (gaffitter)
//
//   Copyright (C) 2005-2015 Douglas A. Augusto
// 
// This file is part of gaffitter.
// 
// gaffitter 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 3 of the License, or (at
// your option) any later version.
// 
// gaffitter 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 gaffitter; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------

#ifndef input_hh
#define input_hh

#include <string>
#include <vector>

#include "Params.h"

// ----------------------------------------------------------------------------
/** 
 * @class SizeName
 * @brief Contains the size and the name of a file/item.
 */
class SizeName {
public:
   SizeName( const std::string id, const Params::Size_t size ): 
             m_name( id ), m_size( size ) {}
   /**
    * Returns the filesize.
    */
   Params::Size_t Size() const { return m_size; }
   /**
    * Returns the filename.
    */
   const std::string& Name() const { return m_name; }

public:
   // Comparison functions (for sorting containers)
   
   /**
    * Comparison function for sorting by size (ascending).
    */
   static bool CmpSize(const SizeName* a, const SizeName* b)
   {
      return a->Size() < b->Size();
   }
   /**
    * Comparison function for sorting by size (descending).
    */
   static bool CmpSizeRev(const SizeName* a, const SizeName* b)
   {
      return a->Size() > b->Size();
   }
   /**
    * Comparison function for sorting by name (ascending).
    */
   static bool CmpName(const SizeName* a, const SizeName* b)
   {
      return a->Name() < b->Name();
   }
   /**
    * Comparison function for sorting by name (descending).
    */
   static bool CmpNameRev(const SizeName* a, const SizeName* b)
   {
      return a->Name() > b->Name();
   }
   /**
    * Comparison function for sorting by name (ascending and nocase).
    */
   static bool CmpNameNocase(const SizeName* a, const SizeName* b)
   {
      std::string::const_iterator p = a->Name().begin(), q = b->Name().begin();

      while (p != a->Name().end() && q != b->Name().end() && toupper(*p)
                                                          == toupper(*q)) 
      { 
         ++p; ++q; 
      }

      if (p == a->Name().end()) return q != b->Name().end();
      if (q == b->Name().end()) return false;

      return toupper(*p) < toupper(*q);
   }
   /**
    * Comparison function for sorting by name (descending and nocase).
    */
   static bool CmpNameRevNocase(const SizeName* a, const SizeName* b)
   {
      return !CmpNameNocase(a,b);
   }

private:
   const std::string m_name; /**< Holds the file/item name */
   const Params::Size_t m_size; /**< Holds the file/item size */
};

// ----------------------------------------------------------------------------
class Input {
public:
   /**
    * Input class constructor. Sets \ref DiskUsage::m_block_size (DiskUsage
    * static data member).
    */
   Input( Params& );

   ~Input() { for( unsigned i = 0; i < m_files.size(); ++i ) delete m_files[i]; }
private:
   /** 
    * \brief Performs initial steps.
    *
    * Loads files from input, gets their sizes, filters and adds them.
    */
   void Initialize();
   /**
    * Reads the input directly (--di) instead of files/dir. Reads from
    * stdin and/or args.
    */
   void ReadInput();
   /**
    * Loads files from input (stdin/args).
    */
   void LoadFiles();
   /**
    * Tries to add a file into \ref m_files to be processed.
    */
   void AddFile(const std::string&);
   /**
    * Converts a given string to "size ID" pair and puts it into \ref
    * m_files.
    */
   void StringToSizeID(const std::string&);
   /**
    * Check/filter files bigger than 'target'/'--max-size' and smaller
    * than '--min-size'
    */
   bool CheckRange(const std::string&, Params::Size_t) const;

public:
   /** 
    * \var m_files
    *
    * Contains the size and name of input files (filtered)
    * */
   std::vector<const SizeName*> m_files;
   Params::Size_t m_total_size; /**<Holds the total size of the items */

   /**
    * Global parameters.
    */
   Params& m_params;
};

// ----------------------------------------------------------------------------
#endif
