/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Directory iterator.
 *//*--------------------------------------------------------------------*/

#include "deDirectoryIterator.hpp"
#include "deString.h"

#if (DE_DIRITER == DE_DIRITER_WIN32)
#include <direct.h> /* _chdir() */
#include <io.h>     /* _findfirst(), _findnext() */
#endif

namespace de
{

#if (DE_DIRITER == DE_DIRITER_WIN32)

DirectoryIterator::DirectoryIterator(const FilePath &path) : m_path(FilePath::normalize(path))
{
    DE_CHECK_RUNTIME_ERR(m_path.exists());
    DE_CHECK_RUNTIME_ERR(m_path.getType() == FilePath::TYPE_DIRECTORY);

    m_handle  = _findfirst32((std::string(m_path.getPath()) + "/*").c_str(), &m_fileInfo);
    m_hasItem = m_handle != -1;

    skipCurAndParent();
}

DirectoryIterator::~DirectoryIterator(void)
{
    if (m_handle != -1)
        _findclose(m_handle);
}

bool DirectoryIterator::hasItem(void) const
{
    return m_hasItem;
}

FilePath DirectoryIterator::getItem(void) const
{
    DE_ASSERT(hasItem());
    return FilePath::join(m_path, m_fileInfo.name);
}

void DirectoryIterator::next(void)
{
    m_hasItem = (_findnext32(m_handle, &m_fileInfo) == 0);
    skipCurAndParent();
}

void DirectoryIterator::skipCurAndParent(void)
{
    while (m_hasItem && (deStringEqual(m_fileInfo.name, "..") || deStringEqual(m_fileInfo.name, ".")))
        m_hasItem = (_findnext32(m_handle, &m_fileInfo) == 0);
}

#elif (DE_DIRITER == DE_DIRITER_POSIX)

DirectoryIterator::DirectoryIterator(const FilePath &path)
    : m_path(FilePath::normalize(path))
    , m_handle(DE_NULL)
    , m_curEntry(DE_NULL)
{
    DE_CHECK_RUNTIME_ERR(m_path.exists());
    DE_CHECK_RUNTIME_ERR(m_path.getType() == FilePath::TYPE_DIRECTORY);

    m_handle = opendir(m_path.getPath());
    DE_CHECK_RUNTIME_ERR(m_handle);

    // Find first entry
    next();
}

DirectoryIterator::~DirectoryIterator(void)
{
    closedir(m_handle);
}

bool DirectoryIterator::hasItem(void) const
{
    return (m_curEntry != DE_NULL);
}

FilePath DirectoryIterator::getItem(void) const
{
    DE_ASSERT(hasItem());
    return FilePath::join(m_path, m_curEntry->d_name);
}

void DirectoryIterator::next(void)
{
    do
    {
        m_curEntry = readdir(m_handle);
    } while (m_curEntry && (deStringEqual(m_curEntry->d_name, "..") || deStringEqual(m_curEntry->d_name, ".")));
}

#endif

} // namespace de
