/***************************************************************************
 *   Copyright (C) 2007 by Anistratov Oleg                                 *
 *   ower86@gmail.com                                                      *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License version 2        *
 *   as published by the Free Software Foundation;                         *
 *                                                                         *
 *   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.                          *
 *                                                                         *
 ***************************************************************************/
#include "treeitem.h"

#include <QMapIterator>

int TreeItem::m_sortingOrder  = 0;
int TreeItem::m_sortingColumn = 0;

TreeItem::TreeItem(const QList<QVariant> & data, TreeItem * parent, QString name):
  m_parent(parent),
  m_name(name)
{
  if(parent)
    parent->appendChild(this);

  m_data.insert(Qt::DisplayRole, data);

  for(int i = 0; i < m_data.size(); i++)
    m_columns.append(i);
}

TreeItem::~TreeItem()
{
  foreach(TreeItem* item, m_children)
    delete item;
}

const TreeItem* const TreeItem::child(int row) const
{
  return (m_children.count() > row && row >= 0 ? m_children[row] : NULL);
}

void TreeItem::appendChild(TreeItem* child)
{
  m_children.append(child);
  child->setParent(this);
}

QVariant TreeItem::data(int column, int role, bool with_hidden) const
{
  int visible_cols = m_data[role].count() - m_hiddenColumns.size() * !with_hidden;

  int col = -1;
  int i;
  for(i = 0; i < m_data[role].count(); i++)
  {
    if(!m_hiddenColumns.contains(i))
      col++;
    if(col == column)
      break;
  }

  bool ok = visible_cols > column && column >= 0;// && i < m_data[role].count();

  return (ok ? m_data[role][with_hidden ? column : i/*m_columns[column]*/] : QVariant());
}

int TreeItem::row() const
{
  if(m_parent)
    return m_parent->children()->indexOf(const_cast<TreeItem*>(this));

  return 0;
}

int TreeItem::childCount() const
{
  return m_children.count();
}

int TreeItem::columnCount() const
{
  return m_data[Qt::DisplayRole].count() - m_hiddenColumns.size();
}

void TreeItem::setData(const QList< QVariant > & data, int role)
{
  if(m_data.contains(role))
    m_data[role] = data;
  else
    m_data.insert(role, data);
}

QList<TreeItem*> TreeItem::takeChildren()
{
  QList<TreeItem*> ch(m_children);

  foreach(TreeItem* item, m_children)
     item->setParent(NULL);

  m_children.clear();

  return ch;
}

void TreeItem::deleteChild(TreeItem* item)
{
  if(m_children.contains(item))
  {
    m_children.removeAll(item);
    delete item;
  }
}

void TreeItem::setData(int column, const QVariant & data, int role)
{
  if(m_data.contains(role) && m_data[role].size() >= column)
      m_data[role][column] = data;
  else if(columnCount() >= column)
  {
    QList<QVariant> data_;

    for(int i = 0; i < columnCount(); i++)
      if(column == i)
        data_.append(data);
      else
        data_.append("");

    m_data.insert(role, data_);
  }
}

// void TreeItem::insertColumn(int after, const QVariant& col_data)
// {
//   if(after > columnCount())
//     return;
//
//   QList<QVariant> new_data;
//   int i = 0;
//
//   QMapIterator< int, QList<QVariant> > all_data(m_data);
//
//   while(all_data.hasNext())
//   {
//     all_data.next();
//
//     i = -1;
//     new_data.clear();
//     foreach(QVariant data, all_data.value())
//     {
//       if(i == after)
//       {
//         if(all_data.key() == Qt::DisplayRole)
//           new_data.append(col_data);
//         else
//           new_data.append("");
//
//         new_data.append(data);
//       }
//       else
//         new_data.append(data);
//
//       i++;
//     }
//
//     setData(new_data, all_data.key());
//   }
// }

void TreeItem::hideColumn(int column)
{
//   int sz = m_columns.size();

  if(!m_hiddenColumns.contains(column))
    m_hiddenColumns.append(column);

  foreach(TreeItem* item, m_children)
    item->hideColumn(column);

//   for(int i = 0; i < sz; i++)
//     if(m_columns[i] == column)
//     {
//       m_columns.remove(i);
//       break;
//     }
}

void TreeItem::showColumn(int column)
{
  m_hiddenColumns.removeAll(column);

  foreach(TreeItem* item, m_children)
    item->showColumn(column);


//   int sz = m_columns.size();
//   int prev = -1;
//   int next = m_columns[0];
//
//   for(int i = 0; i < sz; i++)
//   {
//     next = m_columns[i];
//
//     if(prev < column && next > column)
//     {
//       m_columns.insert(i, column);
//       break;
//     }
//
//     prev = next;
//   }
}

void TreeItem::sortChildren(int column, Qt::SortOrder order)
{
  m_sortingColumn = column;

  foreach(TreeItem* item, m_children)
    item->setSortingColumn(column);

  qSort(m_children.begin(), m_children.end(), TreeItem::LessThan);

  foreach(TreeItem* item, m_children)
    item->sortChildren(column, order);
}

bool TreeItem::LessThan(TreeItem * i1, TreeItem * i2)
{
  return i1->data(sortingColumn(), Qt::DisplayRole, true).toString() <
         i2->data(sortingColumn(), Qt::DisplayRole, true).toString();
}

int TreeItem::realColumn(int column) const
{
  int col = -1;
  int i;
  for(i = 0; i < m_data[Qt::DisplayRole].count(); i++)
  {
    if(!m_hiddenColumns.contains(i))
      col++;
    if(col == column)
      break;
  }

  return i;
}

int TreeItem::visibleCols(bool with_hidden, int role) const
{
  return m_data[role].count() - m_hiddenColumns.size() * !with_hidden;
}
