/* 
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 *
 * 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 of the
 * License.
 * 
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */
#include "tut_stdafx.h"

#include "../stub_treenode.h"

#include "base/string_utilities.h"

bool TreeNodeImpl::is_root() const
{
  return true;
};

void TreeNodeImpl::release(){}
void TreeNodeImpl::retain(){}

bool TreeNodeImpl::equals(const mforms::TreeNode &other)
{
  return true;
}

bool TreeNodeImpl::is_valid() const
{
  return true;
}
    
void TreeNodeImpl::set_icon_path(int column, const std::string &icon)
{
  set_string(column+1, icon);
}

void TreeNodeImpl::set_attributes(int column, const mforms::TreeNodeTextAttributes& attrs)
{
  mforms::TreeNodeTextAttributes attributes;

  while(_attributes.size() < (size_t)(column + 1))
    _attributes.push_back(attributes);

  attributes = attrs;
  _attributes[column] = attributes;
}


void TreeNodeImpl::set_string(int column, const std::string &value)
{
  while(_values.size() < (size_t)(column + 1))
    _values.push_back("");

  _values[column] = value;
}

void TreeNodeImpl::set_int(int column, int value){}
void TreeNodeImpl::set_long(int column, boost::int64_t value){}
void TreeNodeImpl::set_bool(int column, bool value){}

std::string TreeNodeImpl::get_string(int column) const
{
  return _values.size() > (size_t)column ? _values[column] : "";
}

int TreeNodeImpl::get_int(int column) const
{
  return 0;
}

boost::int64_t TreeNodeImpl::get_long(int column) const
{
  return 0;
}

bool TreeNodeImpl::get_bool(int column) const
{
  return true;
}
    
int TreeNodeImpl::count() const
{
  return _children.size();
}

std::vector<mforms::TreeNodeRef> TreeNodeImpl::add_node_collection(const mforms::TreeNodeCollectionSkeleton &nodes, int position)
{
  std::vector<TreeNodeImpl*> added_nodes;
  std::vector<mforms::TreeNodeRef> result;

  for (std::vector<std::string>::const_iterator it = nodes.captions.begin();
    it != nodes.captions.end(); ++it)
  {
    TreeNodeImpl* child = new TreeNodeImpl();
    child->_parent = mforms::TreeNodeRef(this);
   
    mforms::TreeNodeRef tmp(child);
    tmp->set_string(0, *it);

    added_nodes.push_back(child);
  }

  // If the new nodes will have childrens as well, inserts them
  if (nodes.children.size())
    add_children_from_skeletons(added_nodes, nodes.children);


  bool at_end = (position == -1);
  for(size_t index = 0; index < added_nodes.size(); index++)
  {
    added_nodes[index]->_parent = mforms::TreeNodeRef(this);

    if ( (int)_children.size() > position && !at_end)
      _children.insert(_children.begin()+position, added_nodes[index]);
    else
      _children.push_back(added_nodes[index]);

    position++;

    result.push_back(mforms::TreeNodeRef(added_nodes[index]));
  }

  return result;
}

mforms::TreeNodeRef TreeNodeImpl::insert_child(int index)
{
  if (index < 0)
  {
    TreeNodeImpl* child = new TreeNodeImpl();
    child->_parent = mforms::TreeNodeRef(this);
    _children.push_back(child);

    return mforms::TreeNodeRef(child);
  }

    TreeNodeImpl* child = new TreeNodeImpl();
    child->_parent = mforms::TreeNodeRef(this);
    _children.insert(_children.begin()+index, child);

    return mforms::TreeNodeRef(child);

}

void TreeNodeImpl::add_children_from_skeletons(std::vector<TreeNodeImpl*> &parents, const std::vector<mforms::TreeNodeSkeleton>& children)
{
  for(size_t child_index = 0; child_index < children.size(); child_index++)
  {
    // Creates "this" child for each parent
    std::vector<TreeNodeImpl*> added_nodes;

    for(size_t index=0; index < parents.size(); index++)
    {
      TreeNodeImpl *child = new TreeNodeImpl();
      child->set_string(0, children[child_index].caption);
      child->set_tag(children[child_index].tag);
      added_nodes.push_back(child);
    }

    // If the new nodes will have childrens as well, inserts them
    if (children[child_index].children.size())
      add_children_from_skeletons(added_nodes, children[child_index].children);

    // Now inserts each children to it's corresponding parent
    for(size_t parent_index = 0; parent_index < parents.size(); parent_index++)
    {
      added_nodes[parent_index]->_parent = mforms::TreeNodeRef(parents[parent_index]);
      parents[parent_index]->_children.push_back(added_nodes[parent_index]);
    }
  }
}  

void TreeNodeImpl::remove_from_parent()
{
  TreeNodeImpl* inner_parent = dynamic_cast<TreeNodeImpl*>(_parent.ptr());

  if (inner_parent)
  {
    if (std::find(inner_parent->_children.begin(), inner_parent->_children.end(), this) != inner_parent->_children.end())
    {
      inner_parent->_children.erase(std::find(inner_parent->_children.begin(), inner_parent->_children.end(), this));
    }
  }
}


mforms::TreeNodeRef TreeNodeImpl::get_child(int index) const
{
  return (_children.size() > (size_t)index) ? mforms::TreeNodeRef(_children[index]) : mforms::TreeNodeRef();
}

mforms::TreeNodeRef TreeNodeImpl::get_parent() const
{
  return _parent;
}

void TreeNodeImpl::remove_children()
{
    mforms::TreeNode::remove_children();
}

void TreeNodeImpl::expand()
{
  _expanded = true;
}

void TreeNodeImpl::collapse()
{
  _expanded = false;
}

bool TreeNodeImpl::is_expanded()
{
  return _expanded;
}

void TreeNodeImpl::set_tag(const std::string &tag)
{
  _tag = tag;
}
std::string TreeNodeImpl::get_tag() const
{
  return _tag;
}

void TreeNodeImpl::set_data(mforms::TreeNodeData *data)
{
  pdata = data;
}

mforms::TreeNodeData *TreeNodeImpl::get_data() const
{
  return pdata;
}

TreeNodeImpl::TreeNodeImpl():
pdata(NULL),
_expanded(false)
{
  _parent = mforms::TreeNodeRef();
}
//------------------------------------------------------------------------------
//void TreeNodeImpl::init()
//{
//  ::mforms::ControlFactory *f= ::mforms::ControlFactory::get_instance();
//
//}
 
