/* common/KMFileEnumerator.cpp
 *
 * Copyright (C) 2023 OpenKylin, Inc
 */

#include "KMFileEnumerator.h"

class KMFileEnumerator::Private
{
public:
    Private(GFileEnumerator *enumerator);
    ~Private();

    GFileEnumerator *m_enumerator = nullptr;
    GError *m_error = nullptr;
};

KMFileEnumerator::Private::Private(GFileEnumerator *enumerator)
{
    m_enumerator = enumerator;
}

KMFileEnumerator::Private::~Private()
{
    if (m_enumerator)
        g_object_unref(m_enumerator);
}

KMFileEnumerator::KMFileEnumerator() { }

// 不进行深拷贝
KMFileEnumerator::KMFileEnumerator(const KMFileEnumerator &other)
{
    d = other.d;
}

KMFileEnumerator::KMFileEnumerator(KMFileEnumerator &&other)
{
    d = other.d;
}

KMFileEnumerator::KMFileEnumerator(GFileEnumerator *enumerator)
{
    if (enumerator)
        d = std::make_shared<Private>(enumerator);
}

KMFileEnumerator::~KMFileEnumerator() { }

// 不进行深拷贝
KMFileEnumerator &KMFileEnumerator::operator=(const KMFileEnumerator &other)
{
    if (this != &other && d->m_enumerator != other.d->m_enumerator)
        d = other.d;

    return *this;
}

KMFileEnumerator &KMFileEnumerator::operator=(KMFileEnumerator &&other)
{
    d = other.d;

    return *this;
}

KMFileEnumerator &KMFileEnumerator::operator=(GFileEnumerator *enumerator)
{
    if (enumerator)
    {
        if (d)
        {
            if (d->m_enumerator == enumerator)
            {
                // do nothing
            }
            else if (d->m_enumerator)
            {
                g_object_unref(d->m_enumerator);
                d->m_enumerator = enumerator;
            }
        }
        else
        {
            d = std::make_shared<Private>(enumerator);
        }
    }
    else
    {
        d.reset();
    }

    return *this;
}

GFileEnumerator *KMFileEnumerator::get()
{
    if (d)
        return d->m_enumerator;
    else
        return nullptr;
}

/*
返回枚举对象中下一个文件的信息。将阻止，直到信息可用。从该函数返回的GFileInfo将包含与创建GFileEnumerator时传递的属性字符串匹配的属性。

有关返回文件顺序的信息，请参阅GFileEnumerator的文档。

出现错误时，返回NULL并将error设置为错误。如果枚举器在末尾，将返回NULL，并且将取消设置错误。
*/
KMFileInfo KMFileEnumerator::nextFile()
{
    if (d && d->m_enumerator)
    {
        return g_file_enumerator_next_file(d->m_enumerator, nullptr, &d->m_error);
    }
    else
    {
        return KMFileInfo(true);
    }
}

std::string KMFileEnumerator::errorMessage() const
{
    if (d && d->m_error)
        return d->m_error->message;
    else
        return "";
}

int KMFileEnumerator::errorCode() const
{
    if (d && d->m_error)
        return d->m_error->code;
    else
        return -1;
}
