/* 
 * © 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __changeobjects_H
#define __changeobjects_H

#include <iostream>
#include <assert.h>
#include "diffchange.h"
#include "grtpp_util.h"

namespace grt 
{


//////////////////////////////////////////////////////////////
class MYSQLGRT_PUBLIC ObjectAttrModifiedChange : public DiffChange
{
  std::string _attr;
  DiffChange* subchange;
public:
  ObjectAttrModifiedChange(const std::string& attr, DiffChange* change) : DiffChange(ObjectAttrModified), _attr(attr), subchange(change) {}
  ~ObjectAttrModifiedChange() { delete subchange; }

  const std::string& get_attr_name() const { return _attr; }
  const DiffChange* get_subchange() const { return subchange; }

  void apply(ValueRef& v)
  {   
    if (is_disabled())
      return;

    ObjectRef obj(ObjectRef::cast_from(v));

    ValueRef avalue= ValueRef(obj.get_member(_attr));
    subchange->apply(avalue);
    obj.set_member(_attr, avalue);
  }

  void dump_log(int level) const
  {
    std::cout << std::string(level, ' ');
    std::cout << get_type_name() << "::" << _attr << std::endl;
    subchange->dump_log(level+1);
  }
};

//////////////////////////////////////////////////////////////
class MYSQLGRT_PUBLIC ValueAddedChange : public DiffChange
{
  ValueRef _v;
public:
  ValueAddedChange(ChangeType type, ValueRef v) : DiffChange(type), _v(copy_value(v, true)) {}

  void apply(ValueRef& v)
  {   
    if (is_disabled())
      return;

    v= copy_value(_v, true);
  }
};

//////////////////////////////////////////////////////////////
class MYSQLGRT_PUBLIC ValueRemovedChange : public DiffChange
{
public:
  ValueRemovedChange() : DiffChange(ValueRemoved) {}

  void apply(ValueRef& v)
  {   
    if (is_disabled())
      return;

    v = ValueRef();
  }
};

////////////////////////////////////////////////////////////////
//class MYSQLGRT_PUBLIC ListItemModifiedChange : public DiffChange
//{
//  int index;
//  DiffChange* subchange;
//public:
//  ListItemModifiedChange(int i, DiffChange* change) : DiffChange(ListItemModified), index(i), subchange(change) {}
//  ~ListItemModifiedChange() { delete subchange; }
//
//  void apply(ValueRef& v)
//  {
//    ValueRef avalue= ValueRef(myx_grt_list_item_get(v.valueptr(), index));
//    subchange->apply(avalue);
//    myx_grt_list_item_set(v.valueptr(), index, avalue.valueptr());
//  }
//
//  void dump_log(int level) const
//  {
//    std::cout << std::string(level, ' ');
//    std::cout << get_type_name() << "::" << index <<  std::endl;
//    subchange->dump_log(level+1);
//  }
//};
//
//
////////////////////////////////////////////////////////////////
//class MYSQLGRT_PUBLIC ListItemAddedChange : public DiffChange
//{
//  int index;
//  ValueRef _v;
//public:
//  ListItemAddedChange(int i, ValueRef v) : DiffChange(ListItemAdded), _v(ValueRef::deep_copy<ValueRef>(v)), index(i) {}
//
//  void apply(ValueRef& v)
//  {
//    myx_grt_list_item_insert(v.valueptr(), index, _v.valueptr());
//  }
//
//  void dump_log(int level) const
//  {
//    std::cout << std::string(level, ' ');
//    std::cout << get_type_name() << "::" << index <<  std::endl;
//  }
//};
//
//
////////////////////////////////////////////////////////////////
//class MYSQLGRT_PUBLIC ListItemRemovedChange : public DiffChange
//{
//  int index;
//public:
//  ListItemRemovedChange(int i) : DiffChange(ListItemRemoved), index(i) {}
//
//  void apply(ValueRef& v)
//  {
//    myx_grt_list_item_del(v.valueptr(), index);
//  }
//
//  void dump_log(int level) const
//  {
//    std::cout << std::string(level, ' ');
//    std::cout << get_type_name() << "::" << index <<  std::endl;
//  }
//};
//
////////////////////////////////////////////////////////////////
//class MYSQLGRT_PUBLIC ListOrderChange : public DiffChange
//{
//  std::list<std::string> ids;
//  void set_ids(ListValue<ObjectRef>& source, ListValue<ObjectRef>& target);
//  void apply_order(ListValue<ObjectRef>& list);
//public:
//  ListOrderChange(ValueRef source, ValueRef target) : DiffChange(ListOrderChanged) 
//  {
//    set_ids(ListValue<ObjectRef>::cast_from(source), ListValue<ObjectRef>::cast_from(target));
//  }
//
//  void apply(ValueRef& v)
//  {
//    apply_order(ListValue<ObjectRef>::cast_from(v));
//  }
//
//  //void dump_log(int level) const
//  //{
//  //  std::cout << std::string(level, ' ');
//  //  std::cout << get_type_name() << "::" << index <<  std::endl;
//  //}
//};

//////////////////////////////////////////////////////////////
class MYSQLGRT_PUBLIC DictItemModifiedChange : public DiffChange
{
  std::string key;
  DiffChange* subchange;
public:
  DictItemModifiedChange(const std::string& i, DiffChange* change) : DiffChange(DictItemModified), key(i), subchange(change) {}
  ~DictItemModifiedChange() { delete subchange; }

  void apply(ValueRef& v)
  {   
    if (is_disabled())
      return;

    DictRef dict(DictRef::cast_from(v));
    ValueRef avalue= dict.get(key);
    subchange->apply(avalue);
    dict.set(key, avalue);
  }

  void dump_log(int level) const
  {
    std::cout << std::string(level, ' ');
    std::cout << get_type_name() << "::" << key <<  std::endl;
    subchange->dump_log(level+1);
  }
};


//////////////////////////////////////////////////////////////
class MYSQLGRT_PUBLIC DictItemAddedChange : public DiffChange
{
  ValueRef _v;
  std::string key;
public:
  DictItemAddedChange(const std::string& i, ValueRef v) : DiffChange(DictItemAdded), _v(copy_value(v, true)), key(i) {}

  void apply(ValueRef& v)
  {   
    if (is_disabled())
      return;

    DictRef dict(DictRef::cast_from(v));
    dict.set(key, _v);
  }

  void dump_log(int level) const
  {
    std::cout << std::string(level, ' ');
    std::cout << get_type_name() << "::" << key <<  std::endl;
  }
};


//////////////////////////////////////////////////////////////
class MYSQLGRT_PUBLIC DictItemRemovedChange : public DiffChange
{
  std::string key;
public:
  DictItemRemovedChange(const std::string& i) : DiffChange(DictItemRemoved), key(i) {}

  void apply(ValueRef& v)
  {   
    if (is_disabled())
      return;

    DictRef::cast_from(v).remove(key);
  }

  void dump_log(int level) const
  {
    std::cout << std::string(level, ' ');
    std::cout << get_type_name() << "::" << key <<  std::endl;
  }
};

//////////////////////////////////////////////////////////////
class MYSQLGRT_PUBLIC SimpleValueChange : public DiffChange
{
  ValueRef _old;
  ValueRef _v;
public:


  SimpleValueChange(ValueRef old, ValueRef v) 
    : DiffChange(SimpleValue), _old(copy_value(old, false)), _v(copy_value(v, false)) 
  {}

  ValueRef get_new_value() const { return _v; }
  ValueRef get_old_value() const { return _old; }

  void apply(ValueRef& v)
  {   
    if (is_disabled())
      return;

    v= copy_value(_v, true);
  }

  virtual void dump_log(int level) const
  {
    std::cout << std::string(level, ' ');
    std::cout << get_type_name();
    std::cout << " new:" << _v.repr();
    std::cout << " old:" << _old.repr();
    std::cout << std::endl;
  }
};


//////////////////////////////////////////////////////////////

}
#endif
