/*
 * Array.cpp
 *
 * Copyright (c) 2009 Jonathan Beck All Rights Reserved.
 *
 * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <plist/Array.h>

#include <algorithm>
#include <climits>
#include <cstdlib>

namespace PList
{

Array::Array(Node* parent) : Structure(PLIST_ARRAY, parent)
{
    _array.clear();
}

static void array_fill(Array *_this, std::vector<Node*> &array, plist_t node)
{
    plist_array_iter iter = NULL;
    plist_array_new_iter(node, &iter);
    plist_t subnode;
    do {
        subnode = NULL;
        plist_array_next_item(node, iter, &subnode);
        array.push_back( Node::FromPlist(subnode, _this) );
    } while (subnode);
    free(iter);
}

Array::Array(plist_t node, Node* parent) : Structure(parent)
{
    _node = node;
    array_fill(this, _array, _node);
}

Array::Array(const PList::Array& a)
{
    _array.clear();
    _node = plist_copy(a.GetPlist());
    array_fill(this, _array, _node);
}

Array& Array::operator=(const PList::Array& a)
{
    plist_free(_node);
    for (size_t it = 0; it < _array.size(); it++) {
        delete _array.at(it);
    }
    _array.clear();
    _node = plist_copy(a.GetPlist());
    array_fill(this, _array, _node);
    return *this;
}

Array::~Array()
{
    for (size_t it = 0; it < _array.size(); it++) {
        delete (_array.at(it));
    }
    _array.clear();
}

Node* Array::Clone() const
{
    return new Array(*this);
}

Node* Array::operator[](unsigned int array_index)
{
    return _array.at(array_index);
}

void Array::Append(Node* node)
{
    if (node)
    {
        Node* clone = node->Clone();
        UpdateNodeParent(clone);
        plist_array_append_item(_node, clone->GetPlist());
        _array.push_back(clone);
    }
}

void Array::Insert(Node* node, unsigned int pos)
{
    if (node)
    {
        Node* clone = node->Clone();
        UpdateNodeParent(clone);
        plist_array_insert_item(_node, clone->GetPlist(), pos);
        std::vector<Node*>::iterator it = _array.begin();
        it += pos;
        _array.insert(it, clone);
    }
}

void Array::Remove(Node* node)
{
    if (node)
    {
        uint32_t pos = plist_array_get_item_index(node->GetPlist());
        if (pos == UINT_MAX) {
            return;
        }
        plist_array_remove_item(_node, pos);
        std::vector<Node*>::iterator it = _array.begin();
        it += pos;
        _array.erase(it);
        delete node;
    }
}

void Array::Remove(unsigned int pos)
{
    plist_array_remove_item(_node, pos);
    std::vector<Node*>::iterator it = _array.begin();
    it += pos;
    delete _array.at(pos);
    _array.erase(it);
}

unsigned int Array::GetNodeIndex(Node* node) const
{
    std::vector<Node*>::const_iterator it = std::find(_array.begin(), _array.end(), node);
    return std::distance (_array.begin(), it);
}

}  // namespace PList
