//
//
//

#define DBG_LEVEL 3
#include "Raym/Log.h"

#include <process.h>

#include "FFmpeg.h"

using namespace Raym;

namespace ry0
{
namespace iPTd
{

DEFINE_STATIC_MUTEX(mutex_);
static String *ffmpeg_exe_path_ = NULL;

FFmpeg::FFmpeg()
{
    DebugLog2("FFmpeg::FFmpeg()");

    //
    // ffmpeg.exe の確認
    //   自アプリの実行ファイルとと同じディレクトリにある前提
    //
    mutex_.lock();
    while (ffmpeg_exe_path_ == NULL)
    {
        FileManager *fm = FileManager::defaultManager();

        // 実行ファイルのパスを取得する関数は、TrayApp にあるのだが依存したくないので直に書く
        char execute_path[MAX_PATH + 1];
        memset(execute_path, 0x00, sizeof(execute_path));

        TCHAR strbuf[MAX_PATH + 1];
        if (GetModuleFileName(NULL, strbuf, MAX_PATH) == 0)
        {
            DebugLog0("FFmpeg()::FFmpeg()  GetModuleFileName() ng.");
            break;
        }

        errno_t e;
        size_t returnValue;
        e = wcstombs_s(&returnValue, execute_path, sizeof(execute_path), strbuf, _TRUNCATE);
        if (e != 0)
        {
            DebugLog0("FFmpeg()::FFmpeg()  wcstombs_s() ng.");
            break;
        }

        char *p = strrchr(execute_path, '\\');
        if (p == NULL)
        {
            DebugLog0("FFmpeg()::FFmpeg()  strrchr() ng.");
            break;
        }
        ++p;
        *p = '\0';
        strcat_s(execute_path, sizeof(execute_path), "ffmpeg.exe");

        String *path = String::alloc()->initWithUTF8String(execute_path);
        if (path == NULL)
        {
            DebugLog0("FFmpeg()::FFmpeg()  initWithUTF8String() ng.");
            break;
        }

        bool isDirectory = false;
        if (fm->fileExistsAtPath(path, &isDirectory))
        {
            if (!isDirectory)
            {
                ffmpeg_exe_path_ = path;
                ((Object *)ffmpeg_exe_path_)->autorelease(true);
                break;
            }
            else
            {
                DebugLog0("FFmpeg()::FFmpeg()  is directory: \"%s\"", execute_path);
            }
        }
        else
        {
            DebugLog0("FFmpeg()::FFmpeg()  not found: \"%s\"", execute_path);
        }
        path->release();

        break;
    }
    mutex_.unlock();

    // メンバ初期化

}

FFmpeg::~FFmpeg()
{
    stop();

    // メンバ解放

    DebugLog2("FFmpeg::~FFmpeg()");
}

FFmpeg *FFmpeg::alloc()
{
    DebugLog2("FFmpeg::alloc()");

    return new FFmpeg();
}

FFmpeg *FFmpeg::init()
{
    DebugLog2("FFmpeg::init()");

    if (CommandRunner::init() == NULL)
    {
        release();
        return NULL;
    }

    return this;
}

FFmpeg *FFmpeg::retain()
{
    DebugLog2("FFmpeg::retain()");

    CommandRunner::retain();
    return this;
}

FFmpeg *FFmpeg::autorelease()
{
    DebugLog2("FFmpeg::autorelease()");

    CommandRunner::autorelease();
    return this;
}

bool FFmpeg::start()
{
    DebugLog2("FFmpeg::start()");

    setCommandPath(ffmpeg_exe_path_);

    return CommandRunner::start();
}

bool FFmpeg::readLine(String *line)
{
    return false;
}

const char *FFmpeg::className()
{
    return "FFmpeg";
}

#ifndef _WIN32
#pragma mark '
#pragma mark ------- util -------
#endif

Array *STR_ARRAY(const char *str, ...)
{
    Array *result = Array::arrayWithCapacity(0);

    if (str != NULL)
    {
        result->addObject(String::stringWithUTF8String(str));

        va_list ap;
        va_start(ap, str);
        while (true)
        {
            const char *p = va_arg(ap, const char *);
            if (p == NULL)
            {
                break;
            }
            result->addObject(String::stringWithUTF8String(p));
        }
        va_end(ap);
    }

    return result;
}
/*
Dictionary *MODULE(const char *name, Array *opts)
{
    Dictionary *result = Dictionary::dictionaryWithCapacity(0);
    result->setObject(opts, name);
    return result;
}*/

/*
Dictionary *KEY_VAL(const char *key, const char *value)
{
    Dictionary *result = Dictionary::dictionaryWithCapacity(0);
    result->setString(value, key);
    return result;
}

Dictionary *KEY_VAL(const char *key, String *value)
{
    Dictionary *result = Dictionary::dictionaryWithCapacity(0);
    result->setString(value, key);
    return result;
}

Dictionary *KEY_VAL(const char *key, Dictionary *value)
{
    Dictionary *result = Dictionary::dictionaryWithCapacity(0);
    result->setObject(value, key);
    return result;
}*/

} // iPTd
} // ry0
