// EStringList.h
#ifndef ESTRINGLIST_H
#define ESTRINGLIST_H
#include <iostream>
#include <string>
#include <list>
/**
License: See LICENSE file in this directory.
Author: stephan@wanderinghorse.net
*/

/**
This class represents a simple list of std::string objects.  It is a
proxy for a StringList object and only provides a few commonly-used
methods. It does not subclass list<string> because that class has no
virtual destructor, which means undefined behaviour when deleting a
pointer of EStringLast. :/ See the getList() member function for how
to get the underlying list.
*/
using std::string;
using std::list;

class EStringList
{
public:

        typedef std::list<std::string> StringList;
        typedef StringList::iterator StringListIterator;
        typedef StringList::const_iterator StringListConstIterator;

        typedef StringListIterator iterator;
        typedef StringListConstIterator const_iterator;

        // <<'s el.toString() to os.
        friend std::ostream & operator << (std::ostream &os, const EStringList &el);

        // adds el.toString() to string os.
        friend std::string & operator << (std::string &os, const EStringList &el);

        // Adds str to the end of the list.
        friend EStringList & operator += (EStringList &el, const std::string &str);


        EStringList();
        explicit EStringList( const StringList & );
//         EStringList( const EStringList & );
        virtual ~EStringList() {};

        EStringList::iterator begin() { return this->m_list.begin(); };
        EStringList::const_iterator begin() const  { return this->m_list.begin(); };
        EStringList::iterator end() { return this->m_list.end(); };
        EStringList::const_iterator end() const  { return this->m_list.end(); };

        EStringList::StringList & getList() /* const */;

        /**
           Sets the internal StringList to a copy of list.
        */
        void setList( const EStringList::StringList &list );

        /**
           Works similarly to the shell function of the same name.
           Returns the last popped-off argument.
         */
        std::string shift( unsigned int places = 1 );

        /**
           Returns the number of items in the list.
        */
        int count() const;

        static std::string join( const EStringList &strlist, const std::string &separator );
        /**
           converts strlist to an EStringList and returns the same as join( EStringList ... )
           Note that strlist is not const (design flaw), because it is passed to setStringList() of a temp object. :/
         */
        static std::string join( const StringList &strlist, const std::string &separator );

        /**
           Splits seq into a list of elements, separating at token 'separator'. It eliminates "empty"
           entries. e.g., split( "foo:bar:::foobar", ":" ) will return a list containing (foo,bar,foobar),
           without blank entries.
           A toggle, adding the ability to return empty elements, may be added later (i.e., when it's needed).
         */
        static EStringList split( const std::string &seq, const std::string &separator );

        /**
           tokenize() is subtely different from split(): it uses 
           EStdStringTokenizer::tokenize(), which will give results which are
           useful in contexts like parsing command-line arguments (or
           maybe elib::EReadline input).

           Bug: tokenize hoses any quotes in seq :/
         */
        static EStringList tokenize( const std::string &seq, const std::string &separators = string(" ") );

        static EStringList * loadFromFile( const std::string &fn );
        /**
           fn: filename.
           skipComments: lines starting with ';' or '#' are not included.
           skipEmptyLines: empty lines are not included.
           Returns false if it can't read the file, else true.
         */
        bool load( const std::string &fn, bool skipComments = true, bool skipEmptyLines = true );

        std::string randomEntry( bool removeIt = false );

        void clear() { this->m_list.clear(); };

        /**
           Useful if you want to call STL algorithms.
         */
        EStringList::StringList & list() { return this->m_list; };
  /**
  * Makes a std::string of this object, with each entry separated by separator.

  If quoteSpecialTokens is set to true, then any lines in this list
  which "look like they should be quoted" have double-quotes added to
  the front and back.
  */
    virtual std::string toString( const std::string &separator = "\n", bool quoteSpecialTokens = false ) const;

private:
        EStringList::StringList m_list;

};
#endif // ESTRINGLIST_H
