#include "logiccopyimage.h"
#include "src/frame/logger.h"
#include "src/data/datacdrom.h"
#include "src/model/logicmain.h"
#include "src/view/modaldialog.h"
#include "src/process/processgetiso.h"
#include "src/process/processcopydisk.h"
#include "src/process/processcopydiskdl.h"
#include "src/process/processlsof.h"
#include "src/view/tip_burnresult.h"
#include "src/view/execdialog.h"
#include "src/po/translation.h"
#include <QDebug>

LogicCopyImage *LogicCopyImage::m_oInstance = nullptr;
QMutex     LogicCopyImage::m_oMutex;

LogicCopyImage::LogicCopyImage(QObject *parent) :
    QObject(parent),
    m_iSource(-1),
    m_iDestination(-1)
{
    m_oSources.clear();
    m_oDestinations.clear();
    connect(MAIN, &LogicMain::createCopyImage, this, &LogicCopyImage::slotsAddDestination);
    connect(MAIN, &LogicMain::emptyMedium, this, &LogicCopyImage::slotsAddDestination);
    connect(MAIN, &LogicMain::appendableMedium, this, &LogicCopyImage::slotsAddSource);
    connect(MAIN, &LogicMain::finishedMedium, this, &LogicCopyImage::slotsAddSource);

    connect(MAIN, &LogicMain::mediumRmoved, this, &LogicCopyImage::slotsNoMedium);

    connect(MAIN, &LogicMain::burnCopySetting, this, &LogicCopyImage::slotsSetting);
    connect(MAIN, &LogicMain::getISO, this, &LogicCopyImage::slotsCopyImage);
    connect(MAIN, &LogicMain::copyData, this, &LogicCopyImage::slotsCopyData);
    connect(this, SIGNAL(setting(void*)), BUSNESSSETTING, SLOT(load(void *)));
}

LogicCopyImage *LogicCopyImage::instance()
{
    if (nullptr == m_oInstance)
    {
        QMutexLocker locker(&m_oMutex);

        if (nullptr == m_oInstance)
        {
            m_oInstance = new LogicCopyImage();
        }
    }
    return m_oInstance;
}

bool LogicCopyImage::capacity()
{
    DataCDROM *src;
    DataCDROM *des;

    if (m_iDestination == 0) return true;
    if (m_iSource < 0 || m_iDestination < 0) return false;


    src = static_cast<DataCDROM *>(m_oSources.at(m_iSource));
    des = static_cast<DataCDROM *>(m_oDestinations.at(m_iDestination));

    return des->mediumFreeSize() >= src->mediumUsedSize();
}

void LogicCopyImage::updateISOPath(QString path)
{
    DataCDROM *cdrom;

    cdrom = static_cast<DataCDROM *>(m_oDestinations.at(0));
    cdrom->updateDisplay(path);
}

void LogicCopyImage::slotsAddDestination(void *d)
{
    if (-1 != m_oDestinations.indexOf(d))
        return;

    m_oDestinations << d;
    emit sigAddDestination(d);
}

void LogicCopyImage::slotsAddSource(void *d)
{
    if (-1 != m_oSources.indexOf(d))
        return;

    m_oSources << d;
    emit sigAddSource(d);
}

void LogicCopyImage::slotsNoMedium(void *d)
{
    int idx = m_oDestinations.indexOf(d);
    if (-1 != idx)
    {
        m_oDestinations.takeAt(idx);
        emit sigDelDestination(idx);
    }

    idx = m_oSources.indexOf(d);
    if (-1 != idx)
    {
        m_oSources.takeAt(idx);
        emit sigDelSource(idx);
    }
}

void LogicCopyImage::slotsSetting()
{
    DataCDROM *src;
    DataCDROM *des;
    ModalDialog::instance()->showPage(ModalDialog::BusnessSetting);
    ModalDialog::instance()->show();
    src = static_cast<DataCDROM *>(m_oSources.at(m_iSource));
    des = static_cast<DataCDROM *>(m_oDestinations.at(m_iDestination));
    des->setSettingVolumnID(src->settingVolumnID());
    des->setSettingPreparer(src->settingPreparer());
    des->setSettingPublisher(src->settingPublisher());
    des->setSettingCopyright(src->settingCopyright());
    if (0 == m_iDestination)
    {
        des->setSettingClean(false);
        des->setSettingSetOpen(false);
    }
    else
    {
        des->setSettingCloseSession(src->mediumStatus() == DataMedium::MEDIUM_FINALIZED);
        des->setSettingCreateISO(false);
    }
    setting(des);
}

void LogicCopyImage::slotsCopyImage()
{
    DataCDROM *cdrom = static_cast<DataCDROM *>(m_oSources.at(m_iSource));

    if (cdrom->checkUsingOfOtherApp()) {
        return;
    }
    
    ProcessGetISO *getISO = new ProcessGetISO(m_oSources.at(m_iSource), m_oDestinations.at(0), this);
    getISO->exec();
    delete getISO;
}

void LogicCopyImage::slotsCopyData()
{
    DataCDROM *src;
    DataCDROM *des;

    src = static_cast<DataCDROM *>(m_oSources.at(m_iSource));
    des = static_cast<DataCDROM *>(m_oDestinations.at(m_iDestination));

    if (src->checkUsingOfOtherApp()) {
        return;
    }
    
    if(src->mediumType().contains("CD")&&des->mediumType().contains("DVD")){
        EXEC->information("",_("This disc is a CD, and copying to DVD is not supported"),true);
        return;

    }else if(src->mediumType().contains("DVD")&&des->mediumType().contains("CD")){
        EXEC->information("",_("This disc is a DVD, and copying to CD is not supported"),true);
        return;

    }else if(src->mediumType().contains("DVD+R DL") || des->mediumType().contains("DVD+R DL")) {
        ProcessCopyDiskDL copyDisk(m_oSources.at(m_iSource), m_oDestinations.at(m_iDestination));
        copyDisk.execProcess();
    } else {
        ProcessCopyDisk copyDisk(m_oSources.at(m_iSource), m_oDestinations.at(m_iDestination));
        copyDisk.exec();
    }
}

LogicCopyImage::~LogicCopyImage()
{
}
