// -*-c++-*-

// fixg2sxd - a utility to convert fig to sxd format

// Copyright (C) 2003-2022 Alexander Bürger, acfb@users.sourceforge.net

// 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; either version 2 of the
// License, or (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "xmlwrite.h"

using namespace std;

string indent(int l)
{
    ostringstream s;
    for( int i=0; i<l; ++i )
        s.put(' ');
    return s.str();
}

// ------------------------------------------------------------------------

void TextElement::write(ostream& out, int /*level*/, bool /*pretty*/) const
{
    out << text.str();
}

// ------------------------------------------------------------------------

Node::Node( string const& aName )
    : name( aName ),
      indentation(true)
{
}

Node::~Node()
{
    for( attributes_t::iterator i = attributes.begin();
         i != attributes.end(); ++i )
    {
        delete i->second;
    }
    for( vector<Element*>::iterator i = elements.begin();
         i != elements.end(); ++i )
    {
        delete *i;
    }
}

ostringstream& Node::att( string const& attname )
{
#ifdef USE_MAP
    attributes_t::iterator i = attributes.find( attname );
#else
    attributes_t::iterator i = attributes.begin();
    while( i != attributes.end() && i->first != attname )
        ++i;
#endif
    if( i != attributes.end() ) {
        delete i->second;
#ifndef USE_MAP
        attributes.erase(i);
#endif
    }
    ostringstream* o = new ostringstream;
#ifdef USE_MAP
    attributes[ attname ] = o;
#else
    attributes.push_back( pair<string,ostringstream*>( attname, o ) );
#endif
    return *o;
}

Node& Node::subnode( string const& subname )
{
    Node* n = new Node( subname );
    elements.push_back( n );
    return *n;
}

TextElement& Node::text()
{
    TextElement* t = new TextElement();
    elements.push_back( t );
    indentation = false;
    return *t;
}

void Node::write(ostream& out, int level, bool pretty) const
{
    out << indent(level) << '<' << name;
    for( attributes_t::const_iterator i = attributes.begin();
         i != attributes.end(); ++i )
    {
        out << ' ' << i->first << "=\"" << i->second->str() << '"';
    }
    if( elements.empty() ) {
        out << "/>";
        if( pretty )
            out << endl;
    } else {
        out << ">";
        if( pretty && indentation )
            out << endl;
        for( vector<Element*>::const_iterator i = elements.begin();
             i != elements.end(); ++i )
        {
            (*i)->write( out, level+1, pretty && indentation );
        }
        if( pretty && indentation )
            out << indent(level);
        out << "</" << name << '>';
        if( pretty )
            out << endl;
    }
}

// ------------------------------------------------------------------------

#ifdef TEST_XMLWRITE
int main()
{
    Node root("office:body");
    root["hi"] << "ho";
    Node& s = root.subnode("office:bah");
    s["att-no"] << "yes";
    root.text().t() << "this is text!";
    Node& s2 = root.subnode("office:zero");
    s2["att-no"] << "yes";

    cout << root;
}
#endif // TEST_XMLWRITE
