/*
 * --- GSMP-COPYRIGHT-NOTE-BEGIN ---
 * 
 * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
 * Please add additional copyright information _after_ the line containing
 * the GSMP-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
 * the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
 * 
 * GSMP: dam/include/Ascii.hh
 * General Sound Manipulation Program is Copyright (C) 2000 - 2004
 *   Valentin Ziegler and René Rebe
 * 
 * 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; version 2. A copy of the GNU General
 * Public License can be found in the file LICENSE.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT-
 * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * 
 * --- GSMP-COPYRIGHT-NOTE-END ---
 */

#ifndef DAM__ASCII_HH__
#define DAM__ASCII_HH__

#include "SaveDataLexer.hh"
#include <vector>

namespace DAM
{

  // TODO: "const" all Save (StoreConfig*) methods

  class StoreConfig
  {
  public:
    StoreConfig (std::ostream& i_dst_stream, bool i_write_names);

    std::ostream& dst_stream;
    bool write_names;
  };


  class AsciiData
  {
  public:
    virtual void Save (StoreConfig* config) = 0;
    virtual bool Restore (SaveDataLexer& lexer) = 0;
    virtual ~AsciiData () {}
  };


  class BasicAsciiArrayData : public AsciiData
  {
  public:
    virtual void Save (StoreConfig* config);
    virtual bool Restore (SaveDataLexer& lexer);

  protected:
    virtual void StoreImpl (StoreConfig* config) = 0;
    virtual bool RestoreImpl (SaveDataLexer& lexer) = 0;
    virtual void PrepareRestoreImpl () = 0;
  };



  template <typename ELEMENT>
  class AsciiArrayData : public BasicAsciiArrayData
  {
  public:
    typedef ELEMENT ElementData;
    typedef std::vector <ElementData> ElementVector;
    typedef typename ElementVector::iterator iterator;
    typedef typename ElementVector::const_iterator const_iterator;

    ElementData& operator[] (size_t index) { return data[index]; }
    const ElementData& operator[] (size_t index) const { return data[index]; }

    virtual ~AsciiArrayData ();

    ElementData& NewElement ();

    iterator Begin () { return data.begin (); }
    iterator End () { return data.end (); }
    const_iterator Begin () const { return data.begin (); }
    const_iterator End () const { return data.end (); }
    size_t Size () const { return data.size (); }

  protected:
    ElementVector data;

    virtual void StoreImpl (StoreConfig* config);
    virtual bool RestoreImpl (SaveDataLexer& lexer);
    virtual void PrepareRestoreImpl ();
  };


  template <typename BASIC>
  class BasicAsciiData : public AsciiData
  {
  public:
    typedef BASIC BasicData;

    BasicData data;

    BasicData& operator() () { return data; }
    const BasicData& operator() () const { return data; }
  };


  class AsciiInteger : public BasicAsciiData <int64_t>
  {
  public:
    virtual void Save (StoreConfig* config)
    {
      config -> dst_stream << data << std::endl;
    };

    virtual bool Restore (SaveDataLexer& lexer)
    {
      return lexer.SetInteger (&data);
    };
  };

  class AsciiFloat : public BasicAsciiData <double>
  {
    virtual void Save (StoreConfig* config)
    {
      config -> dst_stream << data << std::endl;
    };

    virtual bool Restore (SaveDataLexer& lexer)
    {
      return lexer.SetFloat (&data);
    };
  };

  class AsciiString : public BasicAsciiData <std::string>
  {
    virtual void Save (StoreConfig* config)
    { // TODO: escape quotes etc !!
      config -> dst_stream << "\"" << data << "\"" << std::endl;
    };

    virtual bool Restore (SaveDataLexer& lexer)
    {
      return lexer.SetString (&data);
    };
  };

  class AsciiPtr : public BasicAsciiData <WrapPointer>
  {
    virtual void Save (StoreConfig* config)
    {
      config -> dst_stream << data.Id () << std::endl;
    };

    virtual bool Restore (SaveDataLexer& lexer)
    {
      return lexer.SetPtr (&data);
    };
  };


  class AsciiGather : public AsciiData
  {
  public:
    typedef unsigned int ilevel;

    class Element
    {
    public:
      Element (AsciiData& i_data, const std::string& i_full_name,
	       ilevel i_inheritance_level);

      AsciiData* data;
      std::string full_name;
      ilevel inheritance_level;

      void CallSave (StoreConfig* config);
      bool CallRestore (SaveDataLexer* lexer);

      bool OnLevel (ilevel level) const { return level == inheritance_level; }
    };

    AsciiGather (ilevel i_level, ilevel i_skip_overloads);

    typedef std::vector <Element> ElementVector;
    typedef ElementVector::iterator iterator;
    typedef ElementVector::const_iterator const_iterator;

    const_iterator Begin () const { return data.begin (); }
    const_iterator End () const { return data.end (); }
    size_t Size () const { return data.size (); }

    virtual void Save (StoreConfig* config);
    virtual bool Restore (SaveDataLexer& lexer);

    // The derived class has to implement assignment and copy-ctor !
    void operator = (const AsciiGather& cpy) { /* do not copy layout mapping */ };
    AsciiGather (const AsciiGather&) { /* do not copy layout mapping */ }

  protected:
    ElementVector data;

    ilevel level;
    ilevel skip_overloads;

    iterator Begin () { return data.begin (); }
    iterator End () { return data.end (); }
  };




  class ElementDataWriter
  {
  public:
    ElementDataWriter (StoreConfig* i_config);
    void operator() (AsciiData& data);
 
  private:
    StoreConfig* config;
    int item;
  };

} // end namespace DAM

/* include template implementation */
#define DAM__ASCII_TMPL__
#include "template/Ascii.tcc"
#undef DAM__ASCII_TMPL__

#endif // DAM__ASCII_HH__
