#include "qshell.hpp"

#include <cstdio>
#include <OsSync.h>


// нитка владеющая TWorker
template <typename TWorker>
class Thread : public QThread
{
public:
    explicit Thread(TWorker *worker, QObject *parent = nullptr)
        : QThread(parent), _worker(worker) 
    {
        worker->setParent(nullptr); //  need to move to new thread
        worker->moveToThread(this);
        //start();
    }

    ~Thread() override {
        quit();
        wait();
    }

    TWorker* worker() const {
        return _worker;
    }

protected:
    void run() override {
        QThread::run();
        //delete _worker;
        _worker->deleteLater();
        emit deleteLater();
    }

private:
    TWorker* _worker;
};




//----------------------------------------------------------------------------

QShell::QShell(QObject *parent)
    :QObject(parent)
    , _shell()
    , _thread(nullptr)
{
}

QShell::QShell(StdIO_Device *device
                , shell_t::const_cmd shell_name
                , QObject *parent
        )
:QObject(parent)
, _shell(device, shell_name)
, _thread(nullptr)
{
}

void QShell::init_thread(){
    auto th = new Thread<QShell>(this);
    _thread = th;
    th->connect(th, &QThread::started , this, &QShell::process );
    th->connect(this, &QShell::finished, th, &QThread::quit );
    connect( &shell_service(), &QShellService::request_terminate_all
                    , this, &QShell::terminate
                    , Qt::DirectConnection );
    thread()->start();
}

bool QShell::start(){
    if ( shell().io() != nullptr){
        init_thread();
        return true;
    }
    return false;
}

QShell::~QShell(){
};

void QShell::process(void){
    shell().execute(">");
    emit finished();
}

// берет obj во владение shell(), он будет удален вместе с завершением shell()
void QShell::take_own(QObject&& obj)
{
    obj.connect( this, &QShell::finished, &obj, &QObject::deleteLater );
}


//=============================================================================
QStringList cli::QStringList(const ILinesHystory& src){
    ::QStringList lst;

    auto end = src.end();
    for (auto x = src.begin(); (x != nullptr) && (x < end); x = src.next(x) ){
        lst.append(x);
    }
    
    return lst;
}

