/* 
 * © 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.
 */

#include "stdafx.h"

#include "changeobjects.h"

namespace grt
{

ChangeSet::~ChangeSet()
{
  //for (std::vector<DiffChange*>::iterator iter= changes.begin();
  //     iter != changes.end(); ++iter)
  //  delete *iter;
}

#if 0

MultiChange::MultiChange(ChangeType atype, ChangeSet& changes) 
  : DiffChange(atype)
  , _changes(changes) 
{
  for (ChangeSet::const_iterator iter= _changes.begin(); iter != _changes.end(); ++iter)
  {
    (*iter)->set_parent(this);
  }
}

MultiChange::~MultiChange() 
{ 
  for (ChangeSet::const_iterator iter= _changes.begin(); iter != _changes.end(); ++iter)
  {
    delete *iter;
  }
  _changes.clear();
}

const ChangeSet* MultiChange::subchanges() 
{
  return &_changes;
}

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

  for (ChangeSet::const_iterator iter= _changes.begin(); iter != _changes.end(); ++iter)
  {
    (*iter)->apply(v);
  }
}

    void dump_log(int level) const
    {
      std::cout << std::string(level, ' ');
      std::cout << get_type_name() << std::endl;
      for (ChangeSet::const_iterator iter= _changes.begin(); iter != _changes.end(); ++iter)
      {
        (*iter)->dump_log(level+1);
      }
    }

  };



  //////////////////////////////////////////////////////////////
  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; }

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

      ValueRef avalue= ValueRef(myx_grt_obj_get_value(v.valueptr(), _attr.c_str()));
      subchange->apply(avalue);
      myx_grt_obj_set_value(v.valueptr(), _attr.c_str(), avalue.valueptr());
    }

    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(ValueRef::deep_copy<ValueRef>(v)) {}

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

      v= ValueRef::deep_copy<ValueRef>(_v);
    }
  };

  //////////////////////////////////////////////////////////////
  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)
    {
      DictRef dict(v.valueptr());
      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
  {
    std::string key;
    ValueRef _v;
  public:
    DictItemAddedChange(const std::string& i, ValueRef v) : DiffChange(DictItemAdded), _v(ValueRef::deep_copy<ValueRef>(v)), key(i) {}

    void apply(ValueRef& v)
    {
      DictRef dict(v.valueptr());
      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)
    {
      myx_grt_dict_item_del(v.valueptr(), key.c_str());
    }

    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 _v;
  public:
    SimpleValueChange(ValueRef v) : DiffChange(SimpleValue), _v(ValueRef::deep_copy<ValueRef>(v)) {}

    void apply(ValueRef& v)
    {
      //    assert(_v.type() == v.type());
      v= ValueRef::deep_copy<ValueRef>(_v);
    }
  };


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

}
#endif
//void ListOrderChange::set_ids(ListValue<ObjectRef>& source, ListValue<ObjectRef>& target)
//{
//  ids.clear();
//  bool changed= source.count() != target.count();
//  for(unsigned i= 0; !changed && i < source.count(); ++i)
//  {
//    if (source[i]->id() != target[i]->id())
//      changed= true;
//  }
//
//  if (!changed)
//    return;
//
//  for(unsigned i= 0; i<target.count(); ++i)
//  {
//    ids.push_back(target[i]->id());
//  }
//}
//
//void ListOrderChange::apply_order(ListValue<ObjectRef>& list)
//{
//  if (ids.empty())
//    return;
//  // WARNING this will not work in case if not all changes were applied
//  ListValue<ObjectRef> new_list= list.grt()->clone_value(list);
//  new_list.remove_all();
//  for (std::list<std::string>::iterator iter= ids.begin(); iter!=ids.end(); ++iter)
//  {
//    new_list.insert( ObjectRef( myx_grt_find_object_by_id(list.valueptr(), iter->c_str())));
//  }
//
//  list= new_list;
//}

}
