/*
 * Dictionary.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 <stdlib.h>
#include <plist/Dictionary.h>

namespace PList
{

Dictionary::Dictionary(Node* parent) : Structure(PLIST_DICT, parent)
{
}

static void dictionary_fill(Dictionary *_this, std::map<std::string,Node*> &map, plist_t node)
{
    plist_dict_iter it = NULL;
    plist_dict_new_iter(node, &it);
    plist_t subnode = NULL;
    do {
        char *key = NULL;
        subnode = NULL;
        plist_dict_next_item(node, it, &key, &subnode);
        if (key && subnode)
            map[std::string(key)] = Node::FromPlist(subnode, _this);
        free(key);
    } while (subnode);
    free(it);
}

Dictionary::Dictionary(plist_t node, Node* parent) : Structure(parent)
{
    _node = node;
    dictionary_fill(this, _map, _node);
}

Dictionary::Dictionary(const PList::Dictionary& d) : Structure()
{
    for (Dictionary::iterator it = _map.begin(); it != _map.end(); it++)
    {
        plist_free(it->second->GetPlist());
        delete it->second;
    }
    _map.clear();
    _node = plist_copy(d.GetPlist());
    dictionary_fill(this, _map, _node);
}

Dictionary& Dictionary::operator=(PList::Dictionary& d)
{
    for (Dictionary::iterator it = _map.begin(); it != _map.end(); it++)
    {
        plist_free(it->second->GetPlist());
        delete it->second;
    }
    _map.clear();
    _node = plist_copy(d.GetPlist());
    dictionary_fill(this, _map, _node);
    return *this;
}

Dictionary::~Dictionary()
{
    for (Dictionary::iterator it = _map.begin(); it != _map.end(); it++)
    {
        delete it->second;
    }
    _map.clear();
}

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

Node* Dictionary::operator[](const std::string& key)
{
    return _map[key];
}

Dictionary::iterator Dictionary::Begin()
{
    return _map.begin();
}

Dictionary::iterator Dictionary::End()
{
    return _map.end();
}

Dictionary::iterator Dictionary::Find(const std::string& key)
{
    return _map.find(key);
}

Dictionary::iterator Dictionary::Set(const std::string& key, const Node* node)
{
    if (node)
    {
        Node* clone = node->Clone();
        UpdateNodeParent(clone);
        plist_dict_set_item(_node, key.c_str(), clone->GetPlist());
        delete _map[key];
        _map[key] = clone;
        return _map.find(key);
    }
    return iterator(this->_map.end());
}

Dictionary::iterator Dictionary::Set(const std::string& key, const Node& node)
{
    return Set(key, &node);
}

Dictionary::iterator Dictionary::Insert(const std::string& key, Node* node)
{
    return this->Set(key, node);
}

void Dictionary::Remove(Node* node)
{
    if (node)
    {
        char* key = NULL;
        plist_dict_get_item_key(node->GetPlist(), &key);
        plist_dict_remove_item(_node, key);
        std::string skey = key;
        free(key);
        _map.erase(skey);
        delete node;
    }
}

void Dictionary::Remove(const std::string& key)
{
    plist_dict_remove_item(_node, key.c_str());
    delete _map[key];
    _map.erase(key);
}

std::string Dictionary::GetNodeKey(Node* node)
{
    for (iterator it = _map.begin(); it != _map.end(); ++it)
    {
        if (it->second == node)
            return it->first;
    }
    return "";
}

};
