#ifndef __JString_h__
#define __JString_h__

#include "MString.h"
#include <iostream>
#include <sstream>

namespace coreutils {

   ///
   /// Use the JString object when you need a JSON interface to C++. JString uses
   /// an MString to store a JSON string representing the object(s) contained.
   /// The [] operator is overriden from the ZString and provides a method to
   /// access the objects elements using a named path as the index to the items.
   ///
   /// JString default constructor will create an empty JString object pointing
   /// to an empty string.
   ///
   /// Use a constructor or assignment operator to initialize a JString to an
   /// initial JSON string.
   ///
   /// Several constructors are available including a handle to a std::FILE
   /// object to initialize the JSON string. On destruction the file is saved back.
   ///
   /// The [] operator can be used to access elements within the JSON string. 
   /// Use:
   ///       jstring["key"] = "value";
   ///       std::cout << jstring["key"];
   ///

   class JString : virtual public MString {

    public:

      JString();
      
      void set(ZString &path, ZString &value);

      ///
      /// Use the find method to look through an object for member specified by
      /// the key in parameter 1. The cursor must be pointing to the { character
      /// that begins the object's list.
      ///

      ZString find(ZString path);
      
      bool locate(ZString path);
      bool notfirst;
      ZString path;

      class Proxy {

       public:
	 Proxy(JString &jstring, ZString key) : jstring(jstring), key(key) {}

	 friend std::ostream &operator<<(std::ostream &os, const Proxy &proxy);

	 operator coreutils::ZString () {
	    return jstring.find(key);
	 }

	 operator coreutils::MString () {
	    return jstring.find(key);
	 }

	 operator std::string () {
	    return jstring.find(key).str();
	 }

	 Proxy& operator=(coreutils::MString value) {	    
	    jstring.set(key, value);
	    jstring.changed(key, value);
	    return *this;
	 }

       private:
   	 JString &jstring;
	 ZString key;
      };

      Proxy operator[](coreutils::ZString key) {
	 return Proxy(*this, key);
      }
      
      JString & operator=(coreutils:: ZString value);

      MString pretty();

      virtual void changed(ZString key, ZString value);
      
    private:
      void removeWhitespace();
      
   };

}

#endif
