/*
 * ************************************************************************************************************
 * Author: Marcin Załęczny
 * Copyright (C)2010 Marcin Załęczny <mzaleczny@hotmail.com>
 * License: The GNU Lesser General Public License, version 3.0 (LGPLv3)
 * Library Name: mzstd
 * Version: 1.07
 * First release date:   2010-11-08
 * Current release date: 2011-03-04
 *
 *
 * This file is part of mzstd library
 * 
 * mzstd 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 3 of the License, or
 * (at your option) any later version.
 * 
 * mzstd 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 program. If not, see <http://www.gnu.org/licenses/>.
 * ************************************************************************************************************
 */

#include "mzObjectList.h"
#include "mzFileUtils.h"


CObjectList::CObjectList(ULONG capacity, BOOL deleteObjects)
    : CArrayList(capacity)
{
    this->setRealClassName(L"CObjectList");
    this->_deleteObjectsInDestructor = deleteObjects;
}

CObjectList::~CObjectList() {
    if (this->_items) {
        if (this->_deleteObjectsInDestructor) {
            this->clear();
        } else {
            this->empty();
        }
    }
}

VOID CObjectList::append(CObject* data) {
    __super::append((LONG)data);
}

VOID WINAPI CObjectList::append(CObjectList *lst) {
    if (lst && lst->size() > 0) {
        for (ULONG i = 0; i < lst->size(); i++) {
            this->append(lst->getAt(i));
        }
    }
}

VOID CObjectList::setAt(ULONG pos, CObject* data) {
    if (pos >= this->_size) {
        this->append(data);
    } else {
        CObject* item = (CObject*)this->_items[pos];
        if (item) {
            delete item;
        }
        this->_items[pos] = (LONG)data;
    }
}

VOID CObjectList::addAsFirst(CObject* data) {
    __super::addAsFirst((LONG)data);
}

VOID CObjectList::insert(ULONG pos, CObject* data) {
    __super::insert(pos, (LONG)data);
}

ULONG CObjectList::del(CObject* data) {
    ULONG removed = 0;
	CObject* item;

    for (ULONG i = 0; i < this->_size; i++) {
		item = (CObject*)this->_items[i];
        if ((LONG)item == (LONG)data) {
            for (ULONG j = i + 1; j < this->_size; j++) {
                this->_items[j - 1] = this->_items[j];
            }
            delete item;
            this->_size--;
            removed++;
        }
    }

    return removed;
}

BOOL CObjectList::delFirst(CObject* data) {
    if (this->removeFirst(data)) {
        delete data;
        return TRUE;
    }
    return FALSE;
}

BOOL CObjectList::delAt(ULONG pos) {
    CObject* item = this->removeAt(pos);
    if (item) {
        delete item;
        return TRUE;
    }
    return FALSE;
}

ULONG CObjectList::remove(CObject* data) {
    ULONG removed = 0;
	CObject* item;

    for (ULONG i = 0; i < this->_size; i++) {
		item = (CObject*)this->_items[i];
        if ((LONG)item == (LONG)data) {
            for (ULONG j = i + 1; j < this->_size; j++) {
                this->_items[j - 1] = this->_items[j];
            }
            this->_size--;
            removed++;
        }
    }

    return removed;
}

BOOL CObjectList::removeFirst(CObject* data) {
	CObject* item;
    for (ULONG i = 0; i < this->_size; i++) {
		item = (CObject*)this->_items[i];
        if ((LONG)item == (LONG)data) {
            for (ULONG j = i + 1; j < this->_size; j++) {
                this->_items[j - 1] = this->_items[j];
            }
            this->_size--;
            return TRUE;
        }
    }
    return FALSE;
}

CObject* CObjectList::removeAt(ULONG pos) {
    if (pos >= this->_size) {
        return FALSE;
    }
    CObject* item = (CObject*)this->_items[pos];    
    for (ULONG i = pos + 1; i < this->_size; i++) {
        this->_items[i - 1] = this->_items[i];
    }
    this->_size--;
    return item;
}

LONG CObjectList::pos(CObject* data) {
    return __super::pos((LONG)data);
}

BOOL CObjectList::contains(CObject* data) {
    return this->pos(data) >= 0;
}

VOID CObjectList::clear() {
    if (this->_items) {
        CObject *item;
		for (ULONG i = 0; i < this->_size; i++) {
			item = (CObject*)this->_items[i];
			delete item;
		}
        ZeroMemory(this->_items, sizeof(LONG) * this->_size);
    }
    this->_size = 0;
}

VOID CObjectList::empty() {
    if (this->_items) {
        ZeroMemory(this->_items, sizeof(LONG) * this->_size);
    }
    this->_size = 0;
}

CString CObjectList::toString() {
    CString s;
    for (ULONG i = 0; i < this->_size; i++) {
        s += ((CObject*)this->_items[i])->toString();
        s.append(L"\n");
    }    
    return s;
}

CObject* WINAPI CObjectList::pop() {
    CObject* retval;
    if (this->_size < 1) {
        return NULL;
    }
    retval = (CObject*)this->_items[this->_size - 1];
    this->_items[this->_size - 1] = NULL;
    this->_size--;
    return retval;
}
