#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qfiledialog.h"
#include "qprocess.h"
#include "qdebug.h"
#include "qtimer.h"
#include "qmessagebox.h"
#include "qinputdialog.h"
#include "qformlayout.h"
#include "qdialogbuttonbox.h"
const QString MainWindow::programName = QString("buckshot");
const QString MainWindow::version = QString("0.05");
const QString MainWindow::imageName = QString("saved");

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Window Title
    this->setWindowTitle(QString("%1  v%2").arg(programName,version));

    // SET TEMP DIR FOR CACHE/BUILDING
    tmpDir = new QTemporaryDir();
    if (tmpDir->isValid()) {
        tmpDirPath = tmpDir->path();   // dir.path() returns the unique directory path
    } else {
        tmpDirPath = "/tmp/";          // fallback.  may not work on all OSes
    }

    // AND NOW THE PATHNAMES FOR OUR CACHE FILES
    inputImgPath = QString("%1/%2.bmp").arg(tmpDirPath).arg(imageName);
    previewImgPath = QString("%1/%2_Preview.bmp").arg(tmpDirPath).arg(imageName);

    // POPULATE FORMAT COMBOBOX
    QStringList outputFormats;
    outputFormats << "LR" << "DLR" << "HGR" << "DHGR" << "MONO";
    ui->comboBox_outputFormat->addItems(outputFormats);

    // POPULATE RESOLUTION COMBOBOX
    QStringList inputResolutions;
    inputResolutions << "40 x 48   - Full Scale LGR"
                     << "80 x 48   - Full Scale DLGR"
                     << "140 x 192 - Full Scale (HGR & DHGR)"
                     << "280 x 192 - Double Width Scale (HGR & DHGR)"
                     << "320 x 200 - Classic Size"
                     << "560 x 384 - Quadruple Width, Double Height Scale"
                     << "640 x 400 - Classic Size"
                     << "640 x 480 - Classic Size";
    ui->comboBox_inputResolution->addItems(inputResolutions);

    // POPULATE DITHERING COMBOBOX
    QStringList ditheringAlgorithms;
    ditheringAlgorithms << "Default"
                        << "1- Floyd-Steinberg"
                        << "2- Jarvis"
                        << "3- Stucki"
                        << "4- Atkinson"
                        << "5- Burkes"
                        << "6- Sierra"
                        << "7- Sierra Two"
                        << "8- Sierra Lite"
                        << "9- Buckels";
    ui->comboBox_dithering->addItems(ditheringAlgorithms);


    // POPULATE PALETTE COMBOBOX
    QStringList previewPalettes;
    previewPalettes << "Kegs32 RGB"
            << "CiderPress RGB"
            << "Old AppleWin NTSC"
            << "New AppleWin NTSC"
            << "Wikipedia NTSC"
            << "tohgr NTSC DHGR"
            << " (N/A) -- Imported"
            << "Legacy Canvas"
            << "Legacy Win16"
            << "Legacy Win32"
            << "Legacy VGA BIOS"
            << "Legacy VGA PCX"
            << "Super Convert RGB"
            << "Jace NTSC"
            << "Cybernesto-Munafo NTSC"
            << "Pseudo Palette"
            << "tohgr NTSC HGR";
    ui->comboBox_previewPalette->addItems(previewPalettes);

    // HANDLE DISPLAY MODE SELECTION (COMPATIBILITY)
    updateDisplayModes();

    // live preview stuff
    updateNeeded = false;
    previewTimer = new QTimer(this);
    connect(previewTimer, SIGNAL(timeout()), this, SLOT(previewTimerTimeout()));
    // decided to enable by checking in the form and calling this.
    on_checkBox_livePreview_stateChanged(1);
}


MainWindow::~MainWindow()
{
    delete ui;
}


bool MainWindow::check_canPreview()
{
    if (ui->label_source->pixmap() == nullptr) {
        ui->plainTextEdit_lastCmd->setPlainText("Please open a source image to run a preview!");
        repaint();
        return false;
    }
    return true;
}

bool MainWindow::check_canSave()
{
    if (ui->label_preview->pixmap() == nullptr) {
        ui->plainTextEdit_lastCmd->setPlainText("Please open a source image and run a preview first!");
        repaint();
        return false;
    }
    return true;
}


void MainWindow::updateDisplayModes() {

    QList<int> disabledList = QList<int>();

    //---- display modes
    // 0  "40 x 48   - Full Scale LGR (LGR ONLY)"
    // 1  "80 x 48   - Full Scale DLGR (DLGR ONLY)"
    // 2  "140 x 192 - Full Scale (HGR & DHGR)"
    // 3  "280 x 192 - Double Width Scale (HGR & DHGR)"
    // 4  "320 x 200 - Classic Size"
    // 5  "560 x 384 - Quadruple Width, Double Height Scale"
    // 6  "640 x 400 - Classic Size"
    // 7  "640 x 480 - Classic Size";
    
    // Enable all first
    QList<int> enabledList = QList<int>() << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7;
    QListIterator<int> e(enabledList);
    while (e.hasNext()) {
        // Get the index of the value to disable
        QModelIndex index = ui->comboBox_inputResolution->model()->index(e.next(), 0);
        // enable flag
        QVariant vEnable(1 | 32);
        // the magic
        ui->comboBox_inputResolution->model()->setData(index, vEnable, Qt::UserRole - 1);
    }

    // SET DISABLED ITEMS LIST - AND DEFAULT RESOLUTION FOR MODE
    if (ui->comboBox_outputFormat->currentText() == "LR") {
        disabledList << 2 << 3;
        inputWidth = 40;
        inputHeight = 48;
        ui->comboBox_inputResolution->setCurrentIndex(0);
    } else if (ui->comboBox_outputFormat->currentText() == "DLR") {
        disabledList << 2 << 3;
        inputWidth = 80;
        inputHeight = 48;
        ui->comboBox_inputResolution->setCurrentIndex(1);
    }  else if (ui->comboBox_outputFormat->currentText() == "MONO") {
        disabledList << 0 << 1 << 2 << 4 << 6 << 7;
        inputWidth = 280;
        inputHeight = 192;
        ui->comboBox_inputResolution->setCurrentIndex(3);
    } else if (ui->comboBox_outputFormat->currentText() == "DHGR") {
        inputWidth = 280;
        inputHeight = 192;
        ui->comboBox_inputResolution->setCurrentIndex(3);
    } else {
        inputWidth = 140;
        inputHeight = 192;
        ui->comboBox_inputResolution->setCurrentIndex(2);
    }

    // NOW ACTUALLY DISABLE INVALID RESOLUTIONS IN THE COMBOBOX
    QListIterator<int> d(disabledList);
    while (d.hasNext()) {
        // Get the index of the value to disable
        QModelIndex index = ui->comboBox_inputResolution->model()->index(d.next(), 0);
        // This is the effective 'disable' flag
        QVariant vDisable(0);
        // the magic
        ui->comboBox_inputResolution->model()->setData(index, vDisable, Qt::UserRole - 1);
    }
}


void MainWindow::on_pushButton_sourceFilename_clicked()
{
    QString filename = QFileDialog::getOpenFileName();
    if (filename != nullptr) {
        ui->lineEdit_sourceFilename->setText(filename);
        QPixmap mypix(filename);
        ui->label_source->setPixmap(mypix);
        ui->label_source->setScaledContents(true);
        QSize sourceSize = ui->label_source->pixmap()->size();
        QString resolutionString = QString("%1 x %2").arg(sourceSize.width()).arg(sourceSize.height());
        ui->label_sourceResolution->setText(resolutionString);
        updateNeeded=1;
    }
}


void MainWindow::updateInputSize()
{
    switch (ui->comboBox_inputResolution->currentIndex()) {
    case 0:
        inputWidth = 40;
        inputHeight = 48;
        break;
    case 1:
        inputWidth = 80;
        inputHeight = 48;
        break;
    case 2:
        inputWidth = 140;
        inputHeight = 192;
        break;
    case 3:
        inputWidth = 280;
        inputHeight = 192;
        break;
    case 4:
        inputWidth = 320;
        inputHeight = 200;
        break;
    case 5:
        inputWidth = 560;
        inputHeight = 384;
        break;
    case 6:
        inputWidth = 640;
        inputHeight = 400;
        break;
    case 7:
        inputWidth = 640;
        inputHeight = 480;
        break;
    default:
        qDebug() << "default, error?";
        break;
    }

    QSize sourceSize = ui->label_source->pixmap()->size();
    double sx = static_cast<double>(inputWidth) / sourceSize.width();
    double sy = static_cast<double>(inputHeight) / sourceSize.height();
    QString scaleString = QString("%1 x %2").arg(sx).arg(sy);
    ui->label_scaleFactor->setText(scaleString);
}


void MainWindow::livePreview()
{
    if (ui->checkBox_livePreview->isChecked()) {
        on_pushButton_preview_clicked();
    }
}


// This is the actual preview generation/main logic function
void MainWindow::on_pushButton_preview_clicked()
{
    if (!check_canPreview()) return;

    // GET SCALE FACTOR
    updateInputSize();

    // NOW GENERATE SCALED QPIXMAP TO SAVE
    QPixmap scaledPixmap = ui->label_source->pixmap()->scaled(inputWidth,inputHeight);
    scaledPixmap.save(inputImgPath,"BMP", 0);

    // NOW FIND OUR OUTPUT FORMAT
    QString outputFormat = "H";     // HIRES
    switch (ui->comboBox_outputFormat->currentIndex()) {
    case 0:
        outputFormat = "L";
        break;
    case 1:
        outputFormat = "DL";
        break;
    case 2:
        outputFormat = "H";
        break;
    case 3:
        outputFormat = "D";
        break;
    case 4:
        outputFormat = "mono";
        break;
    }

    QString converterPath = "/Users/dbrock/appleiigs/grlib/b2d";
    converterPath = QString("%1/b2d").arg(QCoreApplication::applicationDirPath());

    QProcess process;
    QStringList args;
    args << inputImgPath;   // "/tmp/saved.bmp"
    args << outputFormat;
    if (outputFormat == "DL" || outputFormat == "L") {
        args << "N";
    }

    if (ui->horizontalSlider_crossHatch->value() > 0) {
        QString crossHatchArg = QString("Z%1").arg(ui->horizontalSlider_crossHatch->value());
        args << crossHatchArg;
    }
    if (ui->horizontalSlider_colorBleed->value() > 0) {
        QString colorBleedArg = QString("R%1").arg(ui->horizontalSlider_colorBleed->value());
        args << colorBleedArg;
    }

    if (ui->comboBox_dithering->currentIndex() > 0) {
        QString ditherArg = QString("D%1").arg(ui->comboBox_dithering->currentIndex());
        args << ditherArg;
    }

    // MUST ALWAYS HAVE A "V" FLAG TO GENERATE OUR PREVIEW IMAGE
    if (ui->comboBox_previewPalette->currentIndex() > -1) {
        QString ppalArg = QString("V%1").arg(ui->comboBox_previewPalette->currentIndex());
        args << ppalArg;
    }

    args << ui->lineEdit_addArgs->text();

    // RUN THE CONVERTER SCRIPT
    process.start(converterPath,args);
    process.waitForFinished();  // BLOCKS!!!

    QString commandString = QString("%1 %2").arg(converterPath, args.join(" "));
    qDebug() << commandString;
    ui->plainTextEdit_lastCmd->document()->setPlainText(commandString);

    // ALL DONE SO TRY TO LOAD PREVIEW
    QPixmap previewPix(previewImgPath);
    float realScale = 1;
    if (previewPix.width() == 80) {
        int scale = 3;
        realScale = scale;
        previewPix = previewPix.scaled(80*scale, 48*scale);
        qDebug() << "W80";
    }
    if (previewPix.width() == 560) {
        float scale = 0.5f;
        realScale = scale;
        previewPix = previewPix.scaled(qRound(560*scale),qRound(384*scale), Qt::KeepAspectRatio,Qt::SmoothTransformation);
        qDebug() << "W560";
    }
    ui->label_preview->setPixmap(previewPix);
    ui->groupBox_preview->setTitle(QString("Preview - Scale %1").arg(qRound(realScale)));
    repaint();
}


// When this timer is running, it checks to see if a
// preview update has been requested, and handles it if so.
void MainWindow::previewTimerTimeout()
{
    if (updateNeeded) {
        on_pushButton_preview_clicked();
        updateNeeded = false;
    }
}


void MainWindow::on_horizontalSlider_crossHatch_valueChanged(int value)
{
    if (value==0){
        ui->label_crossHatch->setText("Off");
    } else {
        ui->label_crossHatch->setText(QString::number(value));
    }
    updateNeeded = 1;
}


void MainWindow::on_horizontalSlider_colorBleed_valueChanged(int value)
{
    if (value==0){
        ui->label_colorBleed->setText("Off");
    } else {
        ui->label_colorBleed->setText(QString::number(value));
    }
    updateNeeded = 1;
}


void MainWindow::on_comboBox_outputFormat_currentIndexChanged(int /*unused*/)
{
    updateNeeded = 1;
    updateDisplayModes();
}


void MainWindow::on_comboBox_inputResolution_currentIndexChanged(int /*unused*/)
{
    updateNeeded = 1;
}


void MainWindow::on_checkBox_livePreview_stateChanged(int arg1)
{
    // preview update timer
    if (arg1) {
        updateNeeded = 1;

        previewTimer->start(500);
    } else {
        previewTimer->stop();
    }
}


void MainWindow::on_actionWhat_is_this_triggered()
{
    QMessageBox msgBox;
    msgBox.setText("Image conversion tool for OSX/Windows/Linux\n"
                   "Take modern image formats (PNG, JPEG, BMP, etc) and convert them for use in your Apple II programs or just for fun.\n\n\n"
                   "*USAGE*\n"
                   "Once you start the program, just \"Open Source Image\", select the \"Apple ][ Display Mode\" you want to convert your image to, "
                   "and click \"Preview\", or even better, click the \"Live Preview\" checkbox to get real-time feedback on your conversion settings.\n\n"
                   "Once you are satisfied with your conversion settings, click \"Save Image File\" to save in one of the Apple ][ image formats based on the display mode.  "
                   "If you want to save that image file directly to a ProDOS volume, that is now supported via the \"Save To ProDOS\" function!\n\n"
                   "Then you can load it up in your favorite emulator, or transfer it to real disks/flash storage to view on glorious vintage hardware.\n\n"
                   "(c)2016-2020 Dagen Brock *\n\n\n * bmp2dhr is by Bill Buckels and CADIUS is by Brutal Deluxe.");
    msgBox.exec();
}


void MainWindow::on_pushButton_saveImage_clicked()
{
    if (!check_canSave()) return;

    QString a2filename;
    QString suffix;
    QString filters = QString("All Images (*.A2FC *.BIN *.SLO *.DLO);;HGR (*.BIN);;DHGR (*.A2FC);;LR (*.SLO);;DLR (*.DLO);;All files (*.*)");
    QString defaultFilter;

    if (ui->comboBox_outputFormat->currentText() == "LR") {
        a2filename = QString("%1/%2.SLO").arg(tmpDirPath,imageName.toUpper());
        suffix = ".SLO";
        defaultFilter = "LR (*.SLO)";
    } else if (ui->comboBox_outputFormat->currentText() == "DLR") {
        a2filename = QString("%1/%2.DLO").arg(tmpDirPath,imageName.toUpper());
        suffix = ".DLO";
        defaultFilter = "DLR (*.DLO)";
    } else if (ui->comboBox_outputFormat->currentText() == "HGR") {
        a2filename = QString("%1/%2CH.BIN").arg(tmpDirPath,imageName.toUpper());
        suffix = ".BIN";
        defaultFilter = "HGR (*.BIN)";
    } else if (ui->comboBox_outputFormat->currentText() == "DHGR") {
        a2filename = QString("%1/%2.A2FC").arg(tmpDirPath,imageName.toUpper());
        suffix = ".A2FC";
        defaultFilter = "DHGR (*.A2FC)";
    } else if (ui->comboBox_outputFormat->currentText() == "MONO") {
        a2filename = QString("%1/%2M.BIN").arg(tmpDirPath,imageName.toUpper());
        suffix = ".BIN";
        defaultFilter = "HGR (*.BIN)";
    }

    // PROMPT FOR SAVE FILENAME AND COPY (HOPEFULLY) TO SAVE FILENAME
    QString saveFile = QFileDialog::getSaveFileName(nullptr, "Save file", QDir::currentPath(), filters, &defaultFilter);
    if (QFile::exists(saveFile)) {
        QFile::remove(saveFile);
    }
    QFile::copy(a2filename, saveFile);
}


// HOLY CRAP WHAT IS THIS??
// Well you see, Johnny, this is a layer of hacks to try
// to wrap CADIUS, but it has no API.  So I can clean this up
// but it's more of a proof of concept.  I think it'd be
// smarter to add JSON output to CADIUS in the long run.
// I consider this small feature a present to the community.
void MainWindow::on_pushButton_saveToProdos_clicked()
{
    if (!check_canSave()) return;

    QString cadiusPath = "/Users/dbrock/appleiigs/tools/Cadius";
    cadiusPath = QString("%1/Cadius").arg(QCoreApplication::applicationDirPath());


    // KSYNTHED=Type(06),AuxType(2000),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)
    QString filetype = "06";
    QString auxtype = "2000";


    QString suffix = ".po";
    QString defaultFilter = tr("All ProDOS Images (*.po *.hdv *.2mg)");
    QString filters = QString(tr("All ProDOS Images (*.po *.hdv *.2mg);;ProDOS Order (*.po);;HDV (*.hdv);;2MG (*.2mg);;All files (*.*)"));


    // PROMPT FOR SAVE FILENAME AND COPY (HOPEFULLY) TO SAVE FILENAME
    QString prodosImageFile = QFileDialog::getSaveFileName(nullptr, "Choose ProDOS Image to Save to", QDir::currentPath(), filters, &defaultFilter, QFileDialog::DontConfirmOverwrite);

    // ALSO GENERATE PRODOS SAFE BASENAME
    QFileInfo fi(prodosImageFile);
    QString prodosVolumeName = fi.baseName().left(15);  // get max volume name
    // EMPTY FILENAME?!
    if (prodosImageFile.length() == 0) {
        return;
    }

    QString imageSize = "140KB";

    // NOW SEE IF IT'S A NEW FILE OR EXISTING IMAGE
    QFileInfo check_file(prodosImageFile);
    // check if file exists and if yes: Is it really a file and no directory?
    if (check_file.exists() && check_file.isFile()) {
        // nothing yet.  We'll open it below, either way.
    } else {
        // NEW FILE, PROMPT FOR IMAGE SIZE
        QMessageBox msgBox;
        msgBox.setText(tr("Select size for new ProDOS image"));
        msgBox.addButton(tr("Cancel"), QMessageBox::NoRole);
        QAbstractButton* pButton140 = msgBox.addButton(tr("140KB"), QMessageBox::ApplyRole);
        QAbstractButton* pButton800 = msgBox.addButton(tr("800KB"), QMessageBox::ApplyRole);
        msgBox.setDefaultButton(QMessageBox::Yes);

        msgBox.exec();

        if (msgBox.clickedButton()==pButton140) {
            // set above, nothing to do
        } else if (msgBox.clickedButton()==pButton800) {
            imageSize = "800KB";
        } else {
            return; // cancelled
        }

        // NOW CREATE AN IMAGE
        QProcess process;
        QStringList args;
        args << "CREATEVOLUME";
        args << prodosImageFile;
        args << prodosVolumeName;
        args << imageSize;
        QString commandString = QString("%1 %2").arg(cadiusPath, args.join(" "));

        // RUN THE IMAGE CREATE
        process.start(cadiusPath,args);
        process.waitForFinished();  // BLOCKS!!!

        // NOW CHECK AGAIN TO SEE IF OUR IMAGE FILE GOT CREATED
        if (check_file.exists() && check_file.isFile()) {
            // qDebug() << "IMAGE FILE CREATED.";
        } else {
            ui->plainTextEdit_lastCmd->document()->setPlainText(QString("Failed creating image with command: %1").arg(commandString));
            return;
        }

        ui->plainTextEdit_lastCmd->document()->setPlainText(commandString);
    }

    // NOW CATALOG WHATEVER IMAGE WE GOT... NEW/EXISTING
    QProcess cat_process;
    QStringList cat_args;
    cat_args << "CATALOG";
    cat_args << prodosImageFile;

    // RUN THE CATALOG AND GET OUTPUT
    cat_process.start(cadiusPath,cat_args);
    cat_process.waitForFinished();  // BLOCKS!!!
    QString cat_output = QString(cat_process.readAllStandardOutput());
    //qDebug() << "CATALOG OUTPUT (cat_output)\n   " << cat_output;

    // regex scanner index
    int pos = 0;
    QStringList list;

    // MUST MATCH FOR NEWLINES (VS USING ^ or &)
    QRegExp vol_rx("\n(/.{1,15}/)\r?\n");
    // OVERWRITE PRODOS VOLUME NAME IF WE KNOW BETTER
    while ((pos = vol_rx.indexIn(cat_output, pos)) != -1) {
        prodosVolumeName = vol_rx.cap(1);
        break;
    }

    // NOW MATCH FOR SOME EXTRA DETAILS JUST BECAUSE WE CAN
    QRegExp rx("(Block|Free|File|Directory) : (\\d+)");
    pos = 0;

    while ((pos = rx.indexIn(cat_output, pos)) != -1) {
        list << rx.cap(1);
        //qDebug() << rx.cap(1);
        pos += rx.matchedLength();
    }

    int diskBlocks, diskFree, diskFiles, diskDirs = 0;
    if (list.length() == 4) {
        diskBlocks = list[0].toInt();
        diskFree = list[1].toInt();
        diskFiles = list[2].toInt();
        diskDirs = list[3].toInt();
    } else {
        ui->plainTextEdit_lastCmd->document()->setPlainText(QString("Failed to catalog ProDOS volume. Make sure that the file is one of: .po .hdv .2mg"));
        return;
    }



    QString a2Filename;
    QString savedFilename;
    if (ui->comboBox_outputFormat->currentText() == "LR") {
        savedFilename = QString("%1/%2.SLO").arg(tmpDirPath,imageName.toUpper());
        a2Filename = QString("%1.SLO").arg(imageName.toUpper());
        auxtype = "0400";    // different auxtype (not that it matters)
    } else if (ui->comboBox_outputFormat->currentText() == "DLR") {
        savedFilename = QString("%1/%2.DLO").arg(tmpDirPath,imageName.toUpper());
        a2Filename = QString("%1.DLO").arg(imageName.toUpper());
        auxtype = "0400";    // different auxtype (not that it matters)
    } else if (ui->comboBox_outputFormat->currentText() == "HGR") {
        savedFilename = QString("%1/%2CH.BIN").arg(tmpDirPath,imageName.toUpper());
        a2Filename = QString("%1CH.BIN").arg(imageName.toUpper());
    } else if (ui->comboBox_outputFormat->currentText() == "DHGR") {
        savedFilename = QString("%1/%2.A2FC").arg(tmpDirPath,imageName.toUpper());
        a2Filename = QString("%1.A2FC").arg(imageName.toUpper());
    } else if (ui->comboBox_outputFormat->currentText() == "MONO") {
        savedFilename = QString("%1/%2M.BIN").arg(tmpDirPath,imageName.toUpper());
        a2Filename = QString("%1M.BIN").arg(imageName.toUpper());
    }


    bool ok = false;
    QString prodosFileName;


    // manually build name/auxtype dialog
    QDialog dialog(this);
    // Use a layout allowing to have a label next to each field
    QFormLayout form(&dialog);

    // Add some text above the fields
    form.addRow(new QLabel(tr("Save Image to ProDOS")));

    // Add the lineEdits with their respective labels
    QList<QLineEdit *> fields;

    QLineEdit *lineEdit = new QLineEdit(&dialog);
    lineEdit->setText(a2Filename);
    QString label = QString("ProDOS Name (max 15 chars):");
    form.addRow(label, lineEdit);

    QLineEdit *lineEdit2 = new QLineEdit(&dialog);
    lineEdit2->setText(auxtype);
    lineEdit2->setInputMask("HHHh");
    QString label2 = QString("Change auxtype (optional): $");
    form.addRow(label2, lineEdit2);

    fields << lineEdit << lineEdit2;


    // Add some standard buttons (Cancel/Ok) at the bottom of the dialog
    QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
                               Qt::Horizontal, &dialog);
    form.addRow(&buttonBox);
    QObject::connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
    QObject::connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));

    // Show the dialog as modal
    if (dialog.exec() == QDialog::Accepted) {
        // If the user didn't dismiss the dialog, do something with the fields
        prodosFileName = fields[0]->text();
        auxtype = fields[1]->text();
        ok = true;
    }


    if (ok && !prodosFileName.isEmpty()) {
        // COPY IT ...  OVER EXISTING NAME?
        QString saveFile = QString("%1/%2").arg(tmpDirPath,prodosFileName);
        QFile::copy(savedFilename, saveFile);

        // GENERATE OUR STUPID _FileInformation.txt in the same directory
        QString fileinfo_text = QString("%1=Type(%2),AuxType(%3),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)").arg(prodosFileName, filetype, auxtype);
        QString fileinfo_file = QString("%1/_FileInformation.txt").arg(tmpDirPath);
        //qDebug() << "TMP FILE: " << fileinfo_file;
        QFile file( fileinfo_file );
        if (file.open(QIODevice::ReadWrite)) {
            QTextStream stream( &file );
            stream << fileinfo_text << endl;
        }

        // NOW ADD / SAVE OUR FILE
        QProcess addfile_process;
        QStringList addfile_args;
        addfile_args << "ADDFILE" << prodosImageFile << prodosVolumeName << saveFile;   // our tmp file

        addfile_process.start(cadiusPath,addfile_args);
        addfile_process.waitForFinished();  // BLOCKS!!!
        QString addfile_output = QString(addfile_process.readAllStandardOutput());

        // IF FILE ALREADY EXISTS, ASK IF THEY WANT TO OVERWRITE
        if (addfile_output.contains("A file already exist with the same name")) {
            QMessageBox::StandardButton reply;
            reply = QMessageBox::question(this, "File exists in image", "File exists, Replace?",
                                          QMessageBox::Yes|QMessageBox::No);
            if (reply == QMessageBox::Yes) {

                // ../tools/Cadius DELETEFILE    <[2mg|hdv|po]_image_path>   <prodos_file_path>
                // YES - DELETE
                QString deleteFile = QString("%1%2").arg(prodosVolumeName,prodosFileName);
                // qDebug() << "DELETEFILE : " <<deleteFile;
                QProcess delfile_process;
                QStringList delfile_args;
                delfile_args << "DELETEFILE";
                delfile_args << prodosImageFile;
                delfile_args << deleteFile;

                // NOW ADD / SAVE OUR FILE
                delfile_process.start(cadiusPath,delfile_args);
                delfile_process.waitForFinished();  // BLOCKS!!!
                QString delfile_output = QString(delfile_process.readAllStandardOutput());
                // MAYBE CHECK? BUT WE CAN JUST TRY TO RESAVE AND FAIL THERE

                // TRY ADDFILE AGAIN
                QProcess addfile2_process;
                QStringList addfile2_args;
                addfile2_args << "ADDFILE" << prodosImageFile << prodosVolumeName << saveFile;   // our tmp file

                addfile2_process.start(cadiusPath,addfile_args);
                addfile2_process.waitForFinished();  // BLOCKS!!!
                QString addfile2_output = QString(addfile2_process.readAllStandardOutput());

                // IF FILE ALREADY EXISTS, ASK IF THEY WANT TO OVERWRITE
                if (addfile2_output.contains("Error :")) {
                    ui->plainTextEdit_lastCmd->document()->setPlainText("Save failed.  Couldn't delete/overwrite file?  I really am not sure what went wrong.  Try saving the pictures to your computer and transferring them to ProDOS with another program.");
                    return;
                }
            } else {
                if (ui->label_preview->pixmap() == nullptr) {
                    ui->plainTextEdit_lastCmd->document()->setPlainText("Save cancelled because file exists.");
                    return;
                }
            }
        }


        // IF WE MADE IT THIS FAR, ALL GOOD?
        QFile::remove(saveFile);    // remove our tmp file
        ui->plainTextEdit_lastCmd->document()->setPlainText("File saved.");

    } else {
        ui->plainTextEdit_lastCmd->document()->setPlainText("Save cancelled.");
        // cancelled?
    }


    return;
}

void MainWindow::on_comboBox_dithering_currentIndexChanged(int /*unused*/)
{
    updateNeeded = 1;
}

void MainWindow::on_comboBox_previewPalette_currentIndexChanged(int /*unused*/)
{
    updateNeeded = 1;
}

void MainWindow::on_pushButton_savePreview_clicked()
{
    if (!check_canSave()) return;
    QString a2filename;

    QString filters = QString("All Images (*.BMP *.PNG);;Bitmap (*.BMP);;PNG (*.PNG);;All files (*.*)");
    QString defaultFilter = "PNG (*.PNG)";
    QString suffix = ".PNG";

    // PROMPT FOR SAVE FILENAME AND COPY (HOPEFULLY) TO SAVE FILENAME
    QString saveFile = QFileDialog::getSaveFileName(nullptr, "Save file", QDir::currentPath(), filters, &defaultFilter);
    if (QFile::exists(saveFile)) {
        QFile::remove(saveFile);
    }

    // TRY TO SET CORRECT TYPE FOR SAVE, DEFAULT TO PNG
    QFileInfo fi(saveFile);
    QString ext = fi.completeSuffix().toUpper();
    if (ext == "BMP") {
        ui->label_preview->pixmap()->save(saveFile,"BMP", 0);
    } else {
        ui->label_preview->pixmap()->save(saveFile,"PNG", 0);
    }
}
