#include "TextureList.h"

#include "Text.h"
#include "Texture.h"

using namespace Framework;

// Contents of the TextureList class
// Constructor
TextureList::TextureList()
    : ReferenceCounter(),
      nextId(0)
{
    textures = new RCArray<Texture>();
    names = new RCArray<Text>();
}

// Destructor
TextureList::~TextureList()
{
    textures->release();
    names->release();
}

// Deletes all textures
__declspec(dllexport) void TextureList::clear()
{
    lock.lockWrite();
    textures->clear();
    names->clear();
    lock.unlockWrite();
}

// Adds a texture to the list
//  t: The texture
//  name: The name under which the texture is stored in the list
bool TextureList::addTexture(Texture* t, const char* name)
{
    lock.lockWrite();
    for (auto i : *names)
    {
        if (i->isEqual(name))
        {
            t->release();
            lock.unlockWrite();
            return 0;
        }
    }
    t->id = nextId++;
    textures->add(t);
    names->add(new Text(name));
    lock.unlockWrite();
    return 1;
}

// Removes a texture from the list
//  name: The name of the texture
void TextureList::removeTexture(const char* name)
{
    lock.lockWrite();
    int index = 0;
    for (auto i : *names)
    {
        if (i->isEqual(name))
        {
            names->remove(index);
            textures->remove(index);
            lock.unlockWrite();
            return;
        }
        index++;
    }
    lock.unlockWrite();
}

// Checks whether a texture has been stored under a specific name
//  name: The name
//  return: true if a texture with the name exists
bool TextureList::hasTexture(const char* name) const
{
    lock.lockRead();
    for (auto i : *names)
    {
        if (i->isEqual(name))
        {
            lock.unlockRead();
            return 1;
        }
    }
    lock.unlockRead();
    return 0;
}

// Returns a specific texture
//  name: The name of the texture
Texture* TextureList::getTexture(const char* name) const
{
    lock.lockRead();
    int index = 0;
    for (auto i : *names)
    {
        if (i->isEqual(name))
        {
            Texture* result = textures->get(index);
            lock.unlockRead();
            return result;
        }
        index++;
    }
    lock.unlockRead();
    return 0;
}

// Returns a specific texture
//  id: The id of the texture
Texture* TextureList::getTexture(int id) const
{
    lock.lockRead();
    for (auto i : *textures)
    {
        if (i->getId() == id)
        {
            Texture* result = dynamic_cast<Texture*>(i->getThis());
            lock.unlockRead();
            return result;
        }
    }
    lock.unlockRead();
    return 0;
}

// Returns a specific texture without increased reference counter
//  name: The name of the texture
Texture* TextureList::zTexture(const char* name) const
{
    lock.lockRead();
    int index = 0;
    for (auto i : *names)
    {
        if (i->isEqual(name))
        {
            Texture* result = textures->z(index);
            lock.unlockRead();
            return result;
        }
        index++;
    }
    lock.unlockRead();
    return 0;
}

// Returns a specific texture without increased reference counter
//  id: The id of the texture
Texture* TextureList::zTexture(int id) const
{
    lock.lockRead();
    for (auto i : *textures)
    {
        if (i->getId() == id)
        {
            lock.unlockRead();
            return i;
        }
    }
    lock.unlockRead();
    return 0;
}