
/*---------------------------------------------------------------------------*/
/* tasks_file.cpp                                                            */
/* copyright (c) innovaphone 2016 - 2026                                     */
/*                                                                           */
/*---------------------------------------------------------------------------*/

#include <platform.h>
#include "sdk/common/os/iomux.h"
#include "sdk/common/interface/task.h"
#include "sdk/common/interface/stask.h"
#include "sdk/common/interface/file.h"
#include "sdk/common/lib/tasks_file.h"

#define DBG(x) //debug->printf x

TaskFileWrite::TaskFileWrite(class STaskContext * context, const char * workingPath, const char * fileName, bool append) : STask(context)
{
    this->workingPath = _strdup(workingPath);
    this->fileName = _strdup(fileName);
    this->append = append;
    buffer = 0;
    file = 0;
    last = false;
}

TaskFileWrite::~TaskFileWrite()
{
    if (buffer) free(buffer);
    if (file) delete file;
    if (this->workingPath) free(this->workingPath);
    if (this->fileName) free(this->fileName);
}

void TaskFileWrite::SStart()
{
    DBG(("%x:TaskFileWrite::SStart(%s%s)", this, workingPath, fileName));
    unsigned lw = (unsigned)strlen(workingPath);
    char * b = (char *)alloca(lw + strlen(fileName) + 1);
    strcpy(b, workingPath);
    strcat(b, fileName);
    file = FileSystem::OpenWriteFile(b, append, 0);
    if (!file) {
        for (unsigned p = lw; b[p]; p++) {
            if (b[p] == '/') {
                b[p] = 0;
                FileSystem::CreateDirectory(b, 0700, 0);
                b[p] = '/';
            }
        }
        file = FileSystem::OpenWriteFile(b, append, 0);
    }
    if (file) {
        bool success = true;
        do {
            TaskProgress();
            thread->wait();
            if (buffer) {
                success = file->Write(buffer, length);
                free(buffer);
                buffer = 0;
            }
        } while (success && !last);
        file->Close();
        delete file;
        file = 0;
        if (success) {
            TaskComplete();
        }
        else {
            TaskFailed();
        }
    }
    else {
        TaskFailed();
    }
}

void TaskFileWrite::write(byte * buffer, unsigned length, bool last)
{
    DBG(("%x:TaskFileWrite::write(length=%u, last=%x)", this, length, last));
    this->buffer = buffer ? (byte *)malloc(length) : 0;
    this->length = length;
    this->last = last;
    memcpy(this->buffer, buffer, length);
    thread->cont();
}

void TaskFileWrite::writeBuffer(byte * buffer, unsigned length, bool last)
{
    DBG(("%x:TaskFileWrite::writeBuffer(length=%u, last=%x)", this, length, last));
    this->buffer = buffer;
    this->length = length;
    this->last = last;
    thread->cont();
}

TaskFileRead::TaskFileRead(class STaskContext * context, const char * workingPath, const char * fileName, unsigned length, bool last) : STask(context)
{
    this->workingPath = _strdup(workingPath);
    this->fileName = _strdup(fileName);
    buffer = 0;
    file = 0;
    this->length = length;
    this->last = last;
}

TaskFileRead::~TaskFileRead()
{
    if (workingPath) free(workingPath);
    if (fileName) free(fileName);
    if (buffer) free(buffer);
    if (file) delete file;
}

void TaskFileRead::SStart()
{
    DBG(("%x:TaskFileRead::SStart(%s%s, length=%u, last=%x)", this, workingPath, fileName, length, last));
    char * b = (char *)alloca(strlen(workingPath) + strlen(fileName) + 1);
    strcpy(b, workingPath);
    strcat(b, fileName);
    file = FileSystem::OpenReadFile(b, 0);
    if (file) {
        do {
            if (length) {
                if (buffer) free(buffer);
                buffer = (byte *)malloc(length);
                length = (unsigned int)file->Read(buffer, (size_t)length);
            }
            if (!last) {
                TaskProgress();
                thread->wait();
            }
        } while (length && !last);
        file->Close();
        delete file;
        file = 0;
        TaskComplete();
    }
    else {
        TaskFailed();
    }
}

void TaskFileRead::read(unsigned length, bool last)
{
    DBG(("%x:TaskFileRead::read(length=%u, last=%x)", this, length, last));
    this->length = length;
    this->last = last;
    thread->cont();
}

TaskDirectoryMonitor::TaskDirectoryMonitor(class STaskContext * context, const char * workingPath, class IInstanceLog * log) : STask(context)
{
    this->log = log;
    this->workingPath = _strdup(workingPath);
    this->directoryMonitor = 0;
}

TaskDirectoryMonitor::~TaskDirectoryMonitor()
{
    if (workingPath) free(workingPath);
    if (directoryMonitor) delete directoryMonitor;
}

void TaskDirectoryMonitor::SStart()
{
    DBG(("%x:TaskDirectoryMonitor::SStart(%s)", this, workingPath));
    directoryMonitor = FileSystem::MonitorDirectory(workingPath, log);
    if (directoryMonitor) {
        do {
            directoryMonitor->Monitor();
            if (!stopped) {
                TaskProgress();
                thread->wait();
            }
        } while (!stopped);
        TaskComplete();
    }
    else {
        TaskFailed();
    }
}

void TaskDirectoryMonitor::Monitor()
{
    thread->cont();
}

const char * TaskDirectoryMonitor::ChangedFile()
{
    return directoryMonitor ? directoryMonitor->ChangedFile() : 0;
}

void TaskDirectoryMonitor::Stop()
{
    ITask::Stop();
    if (directoryMonitor) {
        directoryMonitor->Stop();
    }
}

