/*
 * --- 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/src/Ascii.cc
 * 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 ---
 */

#include <sigc++/sigc++.h>

#include "Ascii.hh"
#include "ForEachIf.hh"

using namespace DAM;

using Utility::for_each_if;
using Utility::for_each_noerror;
using Utility::for_each_if_noerror;


StoreConfig::StoreConfig (std::ostream& i_dst_stream, bool i_write_names)
  : dst_stream (i_dst_stream)
{
  write_names = i_write_names;
  std::scientific(i_dst_stream);
}


ElementDataWriter::ElementDataWriter (StoreConfig* i_config)
  : config (i_config)
{
  item = 0;
}

void ElementDataWriter::operator () (AsciiData& data)
{
  config -> dst_stream << "-";
  if (config -> write_names)
    config -> dst_stream << " /* " << item++ << " */";
  config -> dst_stream << std::endl;
  data.Save (config);
}


void BasicAsciiArrayData::Save (StoreConfig* config)
{
  config -> dst_stream << "{" << std::endl;
  StoreImpl (config);
  config -> dst_stream << "}" << std::endl;
}

  
bool BasicAsciiArrayData::Restore (SaveDataLexer& lexer)
{
  bool error;

  PrepareRestoreImpl ();
  
  if (!lexer.OpenArray ())
    return false;

  while (lexer.NextArrayItem (&error))
    if (error || !RestoreImpl (lexer))
      return false;

  return true;
}


AsciiGather::Element::Element (AsciiData& i_data, const std::string& i_full_name,
			       ilevel i_inheritance_level)
{
  data = &i_data;
  full_name = i_full_name;
  inheritance_level = i_inheritance_level;
}


void AsciiGather::Element::CallSave (StoreConfig* config)
{
  if (config -> write_names)
    config -> dst_stream << "/* " << full_name << " */ ";
  data -> Save (config);
}


bool AsciiGather::Element::CallRestore (SaveDataLexer* lexer)
{
  return data -> Restore (*lexer);
};


AsciiGather::AsciiGather (ilevel i_level, ilevel i_skip_overloads)
{
  level = i_level;
  skip_overloads = i_skip_overloads;
}


void AsciiGather::Save (StoreConfig* config)
{
  using namespace std;

  for (ilevel cur_level = 0; cur_level < level; cur_level++)
    {
      config -> dst_stream << "{" << endl;
      for_each_if (data.begin(), data.end(),
		   bind2nd ( mem_fun_ref (&Element::OnLevel), cur_level ),
		   bind2nd ( mem_fun_ref (&Element::CallSave), config ) );
      config -> dst_stream << "}" << endl;
    }
};


bool AsciiGather::Restore (SaveDataLexer& lexer)
{
  using namespace std;

  for (ilevel cur_level = 0; cur_level < level; cur_level++)
    {
      if (!lexer.OpenBlock ())
	return false;

      if (!for_each_if_noerror (data.begin (), data.end (),
	     bind2nd ( mem_fun_ref (&Element::OnLevel), cur_level ),
	     bind2nd ( mem_fun_ref (&Element::CallRestore), &lexer ) ) )
	return false;

      if (!lexer.CloseBlock ())
	return false;
    }

  for (ilevel skip = 0; skip < skip_overloads; skip++)
    if (!lexer.SkipBlock ())
      return false;

  return true;
};
