// $Id: installreffile.cpp,v 1.56 2008/03/06 21:18:59 hvengel Exp $
//  Little cms - profiler construction set
//Copyright (C) 2005 - 2007 Hal Engel, 2007 Joseph L. Simmon III
//
// THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
// EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
// WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
// INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
// OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
// LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//


#include "installreffile.h"
#include <lprofmain.h>
#include <qtlcmswidgets.h>
#include "main.h"

extern "C" {
#include "lcms.h"
#include "xspect.h"
}

#include <qpushbutton.h>
#include <qmessagebox.h>
#include <qmutex.h>
#include <q3textstream.h>
#include <qfile.h>
#include <q3urloperator.h>
#include <qdir.h>
#include <qdatetime.h>
#include <q3urloperator.h>
#include <QTranslator>


#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32))
#define __WIN32__
#endif

static QMutex mutex;
static QString LogoSerial, LogoDescriptor;
static bool refToOld;

int strMonthToInt(QString m)
{
    if (m == QDate::shortMonthName(1) || m == QDate::longMonthName(1))
        return 1;
    else if (m == QDate::shortMonthName(2) || m == QDate::longMonthName(2))
        return 2;
    else if (m == QDate::shortMonthName(3) || m == QDate::longMonthName(3))
        return 3;
    else if (m == QDate::shortMonthName(4) || m == QDate::longMonthName(4))
        return 4;
    else if (m == QDate::shortMonthName(5) || m == QDate::longMonthName(5))
        return 5;
    else if (m == QDate::shortMonthName(6) || m == QDate::longMonthName(6))
        return 6;
    else if (m == QDate::shortMonthName(7) || m == QDate::longMonthName(7))
        return 7;
    else if (m == QDate::shortMonthName(8) || m == QDate::longMonthName(1))
        return 8;
    else if (m == QDate::shortMonthName(9) || m == QDate::longMonthName(9))
        return 9;
    else if (m == QDate::shortMonthName(10) || m == QDate::longMonthName(10))
        return 10;
    else if (m == QDate::shortMonthName(11) || m == QDate::longMonthName(11))
        return 11;
    else if (m == QDate::shortMonthName(12) || m == QDate::longMonthName(12))
        return 12;
    else 
    {
        qDebug((QString::fromLocal8Bit("Month not found = ") + m).toLocal8Bit());
        return 0;
    }
    
}

void checkHCTAge(QString fn)
{
    QString fileStringTraversal;

    int month, year, day;
     
    QFile ReferenceFileInput(fn);
    ReferenceFileInput.open(QIODevice::ReadOnly);
    Q3TextStream inTargetStream(&ReferenceFileInput);

    bool dateComplete = FALSE;

    inTargetStream >> fileStringTraversal;

    while(fileStringTraversal != QString::fromLocal8Bit("BEGIN_DATA") || !dateComplete)
    {
        inTargetStream >> fileStringTraversal;
        if(fileStringTraversal == QString::fromLocal8Bit("MONTH"))
            inTargetStream >> month;
        if(fileStringTraversal == QString::fromLocal8Bit("DAY"))
            inTargetStream >> day;
        if(fileStringTraversal == QString::fromLocal8Bit("YEAR"))
        {
            inTargetStream >> year;
            dateComplete = TRUE;
        }
    }
    QDate date = QDate::currentDate();
    refToOld = (((date.month() - month) + ((date.year() - year) * 12)) > 36);

    ReferenceFileInput.close();
}

void checkIT8Age(QString fn)
{
    LCMSHANDLE hIT8 = cmsIT8LoadFromFile((const char *) fn.toLocal8Bit());
    QString created = QString::fromLocal8Bit(cmsIT8GetProperty(hIT8, "CREATED"));
    QDate date = QDate::currentDate();
    refToOld = (((date.month() - strMonthToInt(created.left(created.find(QString::fromLocal8Bit(" "))))) + ((date.year() - created.right(4).toInt()) * 12)) > 36);
    refToOld = false;
    cmsIT8Free(hIT8);
}


QString inst_get_QTDIR()
{
    const char* qtdir= "QTDIR";
    return QString::fromLocal8Bit(getenv(qtdir));
}


InstallRefFile::InstallRefFile(QWidget *parent)
    : QDialog(parent, "", 0, Qt::WStyle_SysMenu | Qt::WStyle_MinMax | Qt::WStyle_Title), urlOp(QString::fromLocal8Bit("/"))
{
    setupUi(this);
    
    connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
    connect(buttonOk, SIGNAL(clicked()), this, SLOT(slotOK()));
    connect(buttonHelp, SIGNAL(clicked()), this, SLOT(slotHelpButton()));
    connect(buttonCancel, SIGNAL(clicked()), this, SLOT(slotCancel()));

    mainLabel -> setAutoFillBackground ( true ); 
    QPalette pal = mainLabel-> palette();
    pal.setColor(mainLabel ->  backgroundRole(), Qt::white);
    mainLabel -> setPalette(pal);

    QString temp;

    ref_file a;
    a.get(a);
    dirs.template_dir = a.items.template_dir;
    dirs.ref_dir = a.items.ref_dir;
    dirs.temp_dir = a.items.temp_dir;
    settings = a.items.settings;
    
    TargetSelector->Dir = settings -> readEntry(QString::fromLocal8Bit("/LPROF/Files/referencefile_default_dir"), QDir::homeDirPath());
    TargetSelector->setFilename(QString::fromLocal8Bit(""));
    
    if (!QString::compare(QDir::homeDirPath() + QString (QString::fromLocal8Bit("/")), TargetSelector->ReadDir()) == 0)
        TargetSelector->FillValues();
    
    connect( &urlOp, SIGNAL( finished( Q3NetworkOperation *) ), this, SLOT( slotFileCopied( Q3NetworkOperation * ) ) );
    
    connect(TargetSelector, SIGNAL(valueChanged()), this, SLOT(slotTargetSelectorChanged()));

    copyNum=0;
    
    slotTargetSelectorChanged();
}

void InstallRefFile::slotTargetSelectorChanged()
{
    // qDebug("InstallRefFile::slotTargetSelectorChanged()");
    buttonOk -> setEnabled(TargetSelector -> count() != 0);
    currentDir -> setText(TargetSelector->Dir);
    // qDebug(TargetSelector->Dir);    
}

InstallRefFile::~InstallRefFile()
{
    dialogSize ds;
    ds.put(refile, this -> height(), this -> width());
}


void InstallRefFile::slotFileCopied( Q3NetworkOperation *op )
{
    QString errorInfo;

    if ( !op )
        return;

    mutex.lock();
    if ( op && op->state() == Q3NetworkProtocol::StFailed )
        // The copy operation failed
        // Let users know there is a problem
        QMessageBox::critical( this, tr( "ERROR" ), op->protocolDetail() );
    else if (op -> operation () == Q3NetworkProtocol::OpPut)
    {
        copyNum = copyNum - 1;
        QMessageBox::information( this, tr( "Reference File Installed" ), tr("The reference file was succesfully installed"));
    }
    if (copyNum == 0)
        buttonCancel->setEnabled(true);
    mutex.unlock();
}

TemplateType InstallRefFile::CheckTemplateType()
{
    QFile ReferenceFile(TargetSelector->getFilename());
    ReferenceFile.open(QIODevice::ReadOnly); 
    Q3TextStream checkSets(&ReferenceFile); 
    QString currentString;

    bool logo = false;	
    int SetValue = 0;
    LogoSerial = QString::fromLocal8Bit("");
    LogoDescriptor = QString::fromLocal8Bit("");

    // Begin Error and Type Checking.
    while(!ReferenceFile.atEnd())
    {
        checkSets >> currentString;
        if (currentString == QString::fromLocal8Bit("BEGIN_DATA"))
            break;  // no longer looking at the header section
        else if (currentString == QString::fromLocal8Bit("LGOROWLENGTH"))
            logo = true;
        else if (currentString == QString::fromLocal8Bit("NUMBER_OF_SETS") || currentString == QString::fromLocal8Bit("PATCHES_ACTIVE"))
            checkSets >> SetValue;
        else if (logo && currentString == QString::fromLocal8Bit("CREATED"))
        {
            checkSets >> currentString;
            LogoSerial = currentString.right(currentString.length() - 1).left(currentString.length() - 2);
            int year = LogoSerial.mid(LogoSerial.findRev(QString::fromLocal8Bit("/")) + 1, LogoSerial.length() - LogoSerial.findRev(QString::fromLocal8Bit("/"))).toInt();
            int month = LogoSerial.left(LogoSerial.find(QString::fromLocal8Bit("/"))).toInt();   
            checkSets >> currentString;
            checkSets >> currentString;
            checkSets >> currentString;
            LogoSerial = LogoSerial + QString::fromLocal8Bit(" ") + currentString;
            QDate date = QDate::currentDate();
            refToOld = (((date.month() - month) + ((date.year() - year) * 12)) > 36);
         } 
    }
  
    if (logo)
    {
        int pos = TargetSelector->getFilename().findRev(QString::fromLocal8Bit("/"), TargetSelector->getFilename().length() -1, FALSE); 
        LogoDescriptor = TargetSelector->getFilename().right(TargetSelector->getFilename().length() - (pos + 1));
    }

    ReferenceFile.close();

    switch(SetValue)
    {
        case 24:
            return colorChecker_24;
            break;
        case 140:
            return colorChecker_SG;
            break;
        case 240:
            return colorChecker_DC;
            break;
        case 252:
            checkIT8Age(TargetSelector->getFilename());
            return It8_19column;
            break;
        case 264:
            checkIT8Age(TargetSelector->getFilename());
            return It8_kodak;
            break;
        case 285:
            return DigitaL_TargeT_003;
        case 288:
            if (logo)
                return i1_scanner_14;
            else
            {
                checkIT8Age(TargetSelector->getFilename());
                return It8_22column;
            }
            break;
        default:
            if(SetValue > 288 && SetValue <= 638)
            {
                checkHCTAge(TargetSelector->getFilename());
                return hct;
            }
            else 
                return invalid;  
            break;
    }
}

void InstallRefFile::ConvertHCTrefToCGATS()
{
    QString fileStringTraversal, dayParse, 
            yearParse, manufacturerParse, 
            monthConvertToStringFormat,	IDfieldParse_1, 
            IDfieldParse_2, IDfieldParse_3, 
            IDfieldParse_4, IDfieldParse_5, 
            IDfieldParse_6, mediacodeParse, 
            refnumberParse, reffiletypeParse;

    int monthParse;
    double setnumberGrabFromFile;
     
    QFile ReferenceFileInput(TargetSelector->getFilename());
    ReferenceFileInput.open(QIODevice::ReadOnly);
    Q3TextStream inTargetStream(&ReferenceFileInput);

    int dateCompletionFlag = 0;

    QString monthStringFormat[12] = {QString::fromLocal8Bit("Jan"), QString::fromLocal8Bit("Feb"), QString::fromLocal8Bit("March"), QString::fromLocal8Bit("April"), QString::fromLocal8Bit("May"), 
        QString::fromLocal8Bit("June"), QString::fromLocal8Bit("July"), QString::fromLocal8Bit("Aug"), QString::fromLocal8Bit("Sept"), QString::fromLocal8Bit("Oct"), QString::fromLocal8Bit("Nov"), QString::fromLocal8Bit("Dec")};

    inTargetStream >> reffiletypeParse;

    while(fileStringTraversal != QString::fromLocal8Bit("BEGIN_DATA"))
    {
        inTargetStream >> fileStringTraversal;

        if (dateCompletionFlag == 0)
        {
            if(fileStringTraversal == QString::fromLocal8Bit("MONTH"))
                inTargetStream >> monthParse;
            if(fileStringTraversal == QString::fromLocal8Bit("DAY"))
                inTargetStream >> dayParse;
            if(fileStringTraversal == QString::fromLocal8Bit("YEAR"))
            {
                inTargetStream >> yearParse;
                dateCompletionFlag = 1;
            }
        }

        if(fileStringTraversal == QString::fromLocal8Bit("File"))
            inTargetStream >> refnumberParse;
        if(fileStringTraversal == QString::fromLocal8Bit("MEDIA_CODE"))
            inTargetStream >> mediacodeParse;
        if(fileStringTraversal == QString::fromLocal8Bit("MEDIA_MANUFACTURER"))
            inTargetStream >> manufacturerParse;
        if(fileStringTraversal == QString::fromLocal8Bit("SAMPLE_ID"))
            inTargetStream >> IDfieldParse_1 >> IDfieldParse_2 >> 
                        IDfieldParse_3 >> IDfieldParse_4 >> 
                        IDfieldParse_5 >> IDfieldParse_6;
        if(fileStringTraversal == QString::fromLocal8Bit("PATCHES_ACTIVE"))
            inTargetStream >> setnumberGrabFromFile;
    }

    //	************* HEADER CREATION ************************

    QString createdPropertyText, materialPropertyText, serialPropertyText;

    monthConvertToStringFormat = monthStringFormat[monthParse - 1];

    createdPropertyText.append(monthConvertToStringFormat);
    createdPropertyText.append(QString::fromLocal8Bit(", "));
    createdPropertyText.append(dayParse);
    createdPropertyText.append(QString::fromLocal8Bit(" "));
    createdPropertyText.append(yearParse);

    materialPropertyText.append(manufacturerParse);
    materialPropertyText.append(QString::fromLocal8Bit(" "));
    materialPropertyText.append(mediacodeParse);

    serialPropertyText.append(reffiletypeParse);
    serialPropertyText.append(QString::fromLocal8Bit(" "));
    serialPropertyText.append(refnumberParse);

    LCMSHANDLE it8 = cmsIT8Alloc();
    cmsIT8SetSheetType(it8, "LCMS");
    cmsIT8SetPropertyStr(it8, "ORIGINATOR", (const char *) "HutchColor");
    cmsIT8SetPropertyStr(it8, "CREATED", (const char *) createdPropertyText.toLocal8Bit());
    cmsIT8SetPropertyStr(it8, "SERIAL", (const char *) serialPropertyText.toLocal8Bit());
    cmsIT8SetPropertyStr(it8, "MATERIAL", (const char *) materialPropertyText.toLocal8Bit());
    cmsIT8SetPropertyDbl(it8, "NUMBER_OF_SETS", setnumberGrabFromFile);
    cmsIT8SetPropertyDbl(it8, "NUMBER_OF_FIELDS", 7);

    int nFields = 0;

    cmsIT8SetDataFormat(it8, nFields++, "SAMPLE_ID");

    cmsIT8SetDataFormat(it8, nFields++, IDfieldParse_1.toLocal8Bit());
    cmsIT8SetDataFormat(it8, nFields++, IDfieldParse_2.toLocal8Bit());
    cmsIT8SetDataFormat(it8, nFields++, IDfieldParse_3.toLocal8Bit());
    cmsIT8SetDataFormat(it8, nFields++, IDfieldParse_4.toLocal8Bit());
    cmsIT8SetDataFormat(it8, nFields++, IDfieldParse_5.toLocal8Bit());
    cmsIT8SetDataFormat(it8, nFields++, IDfieldParse_6.toLocal8Bit());

    //	************* DATA CREATION ********************

    char patch_id_field[12];
    double field1, field2, field3, field4, field5, field6;

    for (int i = 0; i < setnumberGrabFromFile; i++)
    {
        inTargetStream >> patch_id_field;
        inTargetStream >> field1 >> field2 >> field3 >> field4 >> field5 >> field6;

        if(patch_id_field == "END_DATA")
            break;

        cmsIT8SetData(it8, patch_id_field, "SAMPLE_ID", patch_id_field);
        cmsIT8SetDataDbl(it8, patch_id_field, "XYZ_X", field1);
        cmsIT8SetDataDbl(it8, patch_id_field, "XYZ_Y", field2);
        cmsIT8SetDataDbl(it8, patch_id_field, "XYZ_Z", field3);

        cmsIT8SetDataDbl(it8, patch_id_field, "LAB_L", field4);
        cmsIT8SetDataDbl(it8, patch_id_field, "LAB_A", field5);
        cmsIT8SetDataDbl(it8, patch_id_field, "LAB_B", field6);
    }

    cmsIT8SaveToFile(it8, files.items.targetFile.toLocal8Bit());

    ReferenceFileInput.close();
}

QString InstallRefFile::CreateCustomHCTtemplate()
{
    QString monthStringFormat[12] = {QString::fromLocal8Bit("Jan"), QString::fromLocal8Bit("Feb"), QString::fromLocal8Bit("March"), QString::fromLocal8Bit("April"), QString::fromLocal8Bit("May"), 
        QString::fromLocal8Bit("June"), QString::fromLocal8Bit("July"), QString::fromLocal8Bit("Aug"), QString::fromLocal8Bit("Sept"), QString::fromLocal8Bit("Oct"), QString::fromLocal8Bit("Nov"), QString::fromLocal8Bit("Dec")};

    int i, j;

    // Begin read-in from old target file using CGATS.
    LCMSHANDLE it8read = cmsIT8LoadFromFile(files.items.targetFile.toLocal8Bit());

    QString originatorTextParse, setnumberParse, 
            createdTextParse, serialTextGrab, 
            newProductionDateText, newCreatedText,	
            monthParse, yearParse;

    originatorTextParse = QString::fromLocal8Bit(cmsIT8GetProperty(it8read, "ORIGINATOR"));
    setnumberParse = QString::fromLocal8Bit(cmsIT8GetProperty(it8read, "NUMBER_OF_SETS"));
    serialTextGrab = QString::fromLocal8Bit(cmsIT8GetProperty(it8read, "SERIAL"));
    createdTextParse = QString::fromLocal8Bit(cmsIT8GetProperty(it8read, "CREATED"));
    
    serialTextGrab.remove(QString::fromLocal8Bit(" "));
    
    int textCutOff;
    monthParse = createdTextParse.copy();
    textCutOff = monthParse.find(QString::fromLocal8Bit(","), 0, true);
    monthParse.remove(textCutOff, monthParse.length());
    createdTextParse.remove(0, textCutOff + 2);
    createdTextParse.remove(0, createdTextParse.find(QString::fromLocal8Bit(" ")) + 1);
    yearParse = createdTextParse.copy();

    newProductionDateText = yearParse;
    newProductionDateText.append(QString::fromLocal8Bit(":"));

    QString month_lookup[12][2] = 
    {
        {QString::fromLocal8Bit("Jan"), QString::fromLocal8Bit("01")}, {QString::fromLocal8Bit("Feb"), QString::fromLocal8Bit("02")},  {QString::fromLocal8Bit("March"), QString::fromLocal8Bit("03")},
                                {QString::fromLocal8Bit("April"), QString::fromLocal8Bit("04")}, {QString::fromLocal8Bit("May"), QString::fromLocal8Bit("05")},  {QString::fromLocal8Bit("June"), QString::fromLocal8Bit("06")},
                                        {QString::fromLocal8Bit("July"), QString::fromLocal8Bit("07")}, {QString::fromLocal8Bit("Aug"), QString::fromLocal8Bit("08")},  {QString::fromLocal8Bit("Sept"), QString::fromLocal8Bit("09")},
                                                {QString::fromLocal8Bit("Oct"), QString::fromLocal8Bit("10")},  {QString::fromLocal8Bit("Nov"), QString::fromLocal8Bit("11")},  {QString::fromLocal8Bit("Dec"), QString::fromLocal8Bit("12")}
    };

    for(i = 0; i < 12; i++)
    if(monthParse == month_lookup[i][0])
    {
        newProductionDateText.append(month_lookup[i][1]);
        break;
    }

    newCreatedText = monthParse;
    newCreatedText.append(QString::fromLocal8Bit(", "));
    newCreatedText.append(yearParse);
		
    LCMSHANDLE it8 = cmsIT8Alloc();

    cmsIT8SetSheetType(it8, "TEMPLATE");
    cmsIT8SetPropertyStr(it8, "ORIGINATOR", originatorTextParse.toLocal8Bit());
    cmsIT8SetPropertyStr(it8, "DESCRIPTOR", (const char *) "HCT 4096 Template");
    cmsIT8SetPropertyStr(it8, "CREATED", newCreatedText.toLocal8Bit());
    cmsIT8SetPropertyStr(it8, "MANUFACTURER", (const char *) "lprof");
    cmsIT8SetPropertyStr(it8, "PROD_DATE", (const char *) newProductionDateText.toLocal8Bit());
    cmsIT8SetPropertyDbl(it8, "NUMBER_OF_FIELDS", 5);
    cmsIT8SetPropertyDbl(it8, "NUMBER_OF_SETS", setnumberParse.toDouble(0));

    int nFields = 0;
    double field1, field2, field3, field4;

    cmsIT8SetDataFormat(it8, nFields++, "SAMPLE_ID");
    cmsIT8SetDataFormat(it8, nFields++, "POS_X");
    cmsIT8SetDataFormat(it8, nFields++, "POS_Y");
    cmsIT8SetDataFormat(it8, nFields++, "SIZE_X");
    cmsIT8SetDataFormat(it8, nFields++, "SIZE_Y");

    QString newTemplateFile = dirs.template_dir + QString::fromLocal8Bit("/") + serialTextGrab + QString::fromLocal8Bit(".ITX2");
    cmsIT8SaveToFile(it8, newTemplateFile.toLocal8Bit());

    //	File Streaming code will traverse together until both source and target files
    //	match at the same position (after "BEGIN_DATA").

    QString fileStringTraversalCmp, fileStringTraversal;

    QFile newTargetFile(files.items.targetFile);
    newTargetFile.open(QIODevice::ReadOnly);
    Q3TextStream newTargetStream(&newTargetFile);

    while(fileStringTraversal != QString::fromLocal8Bit("BEGIN_DATA"))
        newTargetStream >> fileStringTraversal;

    QFile sourceTargetFile(dirs.template_dir + QString::fromLocal8Bit("/") + QString::fromLocal8Bit("hutchtone.ITX"));
    sourceTargetFile.open(QIODevice::ReadOnly);
    Q3TextStream compare(&sourceTargetFile);
	   
    while(fileStringTraversalCmp != QString::fromLocal8Bit("BEGIN_DATA"))
        compare >> fileStringTraversalCmp;

    // Begin writing and comparison of HCT patches (from old to new)

    char patch_id_field[12];
    char original_patch_id[12];

    for (i = 0; i < setnumberParse.toInt(0, 10); i++)
    {
        QString dummyParse;

        newTargetStream >> patch_id_field;
        for (j = 0; j < 6; j++)
            newTargetStream >> dummyParse;

        do
        {
            compare >> original_patch_id;
            compare >> field1 >> field2 >> field3 >> field4;
        } while(strcmp(patch_id_field, original_patch_id) == 1);

        cmsIT8SetData(it8, patch_id_field, "SAMPLE_ID", patch_id_field);
        cmsIT8SetDataDbl(it8, patch_id_field, "POS_X", field1);
        cmsIT8SetDataDbl(it8, patch_id_field, "POS_Y", field2);
        cmsIT8SetDataDbl(it8, patch_id_field, "SIZE_X", field3);
        cmsIT8SetDataDbl(it8, patch_id_field, "SIZE_Y", field4);
    }

    cmsIT8SaveToFile(it8, newTemplateFile.toLocal8Bit());
            
    newTargetFile.close();
    sourceTargetFile.close();

    return (newTemplateFile);
}

void InstallRefFile::slotOK()
{	
    refToOld = FALSE;
    bool success = FALSE;
    if (TargetSelector -> count() != 0)  // something is wrong no file is availble to process
    {    	
        files.items.targetFile = dirs.ref_dir + 
                TargetSelector->getFilename().mid(TargetSelector->getFilename().findRev(QString::fromLocal8Bit("/"), -1),
                        TargetSelector->getFilename().length());
                
        dialogSize ds;
        
        switch(CheckTemplateType())
        {
            case hct:
                if (refNotToOld())
                {
                    ConvertHCTrefToCGATS();
                    files.items.templateFile = CreateCustomHCTtemplate();
                    success = TRUE;
                }
                break;
    
            case colorChecker_24:
                CopyTemplateFunction(colorChecker_24);
                break;
    
            case It8_22column:
                if (refNotToOld())
                {
                      CopyTemplateFunction(It8_22column);
                }
                break;
    
            case It8_kodak:
                if (refNotToOld())
                {
                    CopyTemplateFunction(It8_kodak);
                }
                break;
    
            case It8_19column:
                if (refNotToOld())
                {
                    CopyTemplateFunction(It8_19column);
                }
                break;
    
            case colorChecker_DC:
                if (refNotToOld())
                {				
                    CopyTemplateFunction(colorChecker_DC);
                    logoConvert();
                    success = TRUE;
                }		
                break;
    
            case colorChecker_SG:
                if (refNotToOld())
                {
                    CopyTemplateFunction(colorChecker_SG);
                    logoConvert();
                    success = TRUE;
                }	
                break;
                
            case i1_scanner_14:
                if (refNotToOld())
                {
                    CopyTemplateFunction(i1_scanner_14);
                    logoConvert();
                    success = TRUE;
                }	
                break;
               
            case DigitaL_TargeT_003:
                if (refNotToOld())
                {
                    CopyTemplateFunction(DigitaL_TargeT_003);
                    logoConvert();
                    success = TRUE;
                }	
                break;
    
            case invalid:
                QMessageBox::critical(this, tr("Error"), tr("Invalid reference file!"));	
                break;
    
            default:               
                break;
        }
        if (success)
            QMessageBox::information( this, tr( "Reference File Installed" ), tr("The reference file was succesfully installed"));	
    
        files.put(files);	
        ds.put(refile, this -> height(), this -> width());
    }
    else
        QMessageBox::critical( this, tr( "ERROR no reference file available" ), tr("Please specificy a directory that contains one or more reference files." ));

}

void InstallRefFile::slotCancel()
{
    dialogSize ds;

    ds.put(refile, this -> height(), this -> width());

    settings -> writeEntry(QString::fromLocal8Bit("/LPROF/Files/referencefile_default_dir"), TargetSelector->ReadDir());
}

void InstallRefFile::slotHelpButton()
{
    QString path = get_global_help_path() +  QString::fromLocal8Bit("/inst-ref.html");
     getHelp()->openAssistant ();
     getHelp()->showPage(path);
}

void InstallRefFile::CopyTemplateFunction(TemplateType templateCatagory)
{
    QString templateFileName;
    BOOL copy = TRUE;
    
    switch(templateCatagory)
    {
        case colorChecker_24:
            templateFileName = QString::fromLocal8Bit("colorchecker-24p.ITX");
            break;
        case colorChecker_SG:
            templateFileName = QString::fromLocal8Bit("colorchecker-sg.ITX");
            copy = FALSE;
            break;
        case colorChecker_DC:
            templateFileName = QString::fromLocal8Bit("colorchecker-dc.ITX");
            copy = FALSE;
            break;
        case It8_22column:
            templateFileName = QString::fromLocal8Bit("IT8_22.ITX");
            break;
        case It8_kodak:
            templateFileName = QString::fromLocal8Bit("KODAK.ITX");
            break;
        case It8_19column:
            templateFileName = QString::fromLocal8Bit("IT8_19.ITX");
            break;
        case i1_scanner_14:
            templateFileName = QString::fromLocal8Bit("eyeone-template.ITX");
            copy = FALSE;
            break;
        case DigitaL_TargeT_003:
            templateFileName = QString::fromLocal8Bit("DigitaL-TargeT-003.ITX");
            copy = FALSE;
            break;
    }
                            
    files.items.templateFile = dirs.template_dir + QString::fromLocal8Bit("/") + templateFileName;
    files.items.targetFile = dirs.ref_dir + 
            TargetSelector->getFilename().mid(TargetSelector->getFilename().findRev(QString::fromLocal8Bit("/"), -1),
                    TargetSelector->getFilename().length());
    QDir::cleanDirPath( files.items.targetFile );

    if (copy)
    { 
        files.items.targetFile = dirs.ref_dir + 
                TargetSelector->getFilename().mid(TargetSelector->getFilename().findRev(QString::fromLocal8Bit("/"), -1),
                                            TargetSelector->getFilename().length());
        mutex.lock();
        copyNum = copyNum + 1;
        // pull file names out of the dialog
        buttonCancel->setEnabled(false);
        // copy	the reference file to ~/<lprofBaseDir>/target_refs
        urlOp.copy( TargetSelector->getFilename(), dirs.ref_dir + QString::fromLocal8Bit("/"));
        mutex.unlock();
    }
}

void InstallRefFile::CleanKEYWORDS(QString inFile, QString outFile)
{
    QFile ArgyllCGTSFile(inFile);
    QFile cleanCGATS(outFile);
    QString line;
    
    if (ArgyllCGTSFile.open(QIODevice::ReadOnly)) 
    {
        Q3TextStream in(&ArgyllCGTSFile);
        if (cleanCGATS.open(QIODevice::WriteOnly))
        {
            Q3TextStream out(&cleanCGATS);
            int i = 1;
            while ( !in.atEnd() ) 
            {
                line = in.readLine(); // line of text excluding '\n'
                if (line.left(7) != QString::fromLocal8Bit("KEYWORD"))
                {
                    if (line.left(5) == QString::fromLocal8Bit("BEGIN"))
                    {
                        line = QString::fromLocal8Bit("\n") + line;  // Add new line
                    }
                    out << line << "\n";
                }
            }
            ArgyllCGTSFile.close();
            cleanCGATS.close();
        }
        else
        {
            qDebug((QString::fromLocal8Bit("Failed to open cleanCGATS") + outFile).toLocal8Bit());
            qDebug((QString::fromLocal8Bit("Error = ") + cleanCGATS.errorString()).toLocal8Bit());
            ArgyllCGTSFile.close();
        }
    }
    else
    {
        qDebug((QString::fromLocal8Bit("Failed to open ArgyllCGTSFile ") + inFile).toLocal8Bit());
        qDebug((QString::fromLocal8Bit("Error = ") + ArgyllCGTSFile.errorString()).toLocal8Bit());
    }
}

void InstallRefFile::logoConvert()
{
    qDebug("InstallRefFile::logoConvert()");
    
    xspect spectral;
    
    QString CCFilename, created, illum, logoSerial, currentString, numSetsStr, numFieldsStr;
    int numSets, numFields, totalFields;
    
    QString *dataNames;
    bool spec= false;
    const QString newDataNames [6] = { QString::fromLocal8Bit("XYZ_X"),	QString::fromLocal8Bit("XYZ_Y"), QString::fromLocal8Bit("XYZ_Z"), QString::fromLocal8Bit("LAB_L"), QString::fromLocal8Bit("LAB_A"), QString::fromLocal8Bit("LAB_B")};
    double measurement;
    
    int startOfFileName, lowSpec, highSpec, specBands;
    startOfFileName = TargetSelector->getFilename().findRev(QString::fromLocal8Bit("/"), -1);
    CCFilename = TargetSelector->getFilename();		
    CCFilename.remove(0, startOfFileName + 1);
    CCFilename.remove(CCFilename.findRev(QString::fromLocal8Bit("."), -1), 4);
    
    QString fileName = dirs.ref_dir + QString::fromLocal8Bit("/") + CCFilename + QString::fromLocal8Bit(".txt");
    QFile ReferenceFile(TargetSelector->getFilename());
    ReferenceFile.open(QIODevice::ReadOnly);
    Q3TextStream inStream(&ReferenceFile);
    
    logoSerial = QString::fromLocal8Bit("");
    LogoDescriptor = QString::fromLocal8Bit("");
    specBands = 0;
       
    // Header creation.
    while(!ReferenceFile.atEnd())
    {
        inStream >> currentString;
        if (currentString == QString::fromLocal8Bit("BEGIN_DATA"))
            break;  // no longer looking at the header section
        else if (currentString == QString::fromLocal8Bit("NUMBER_OF_SETS") || currentString == QString::fromLocal8Bit("PATCHES_ACTIVE"))
        {
            inStream >> numSetsStr;                    
            numSets = numSetsStr.toInt();
        }
        else if (currentString == QString::fromLocal8Bit("CREATED"))
        {
            inStream >> currentString;
            logoSerial = currentString.right(currentString.length() - 1).left(currentString.length() - 2);
            int year = logoSerial.mid(logoSerial.findRev(QString::fromLocal8Bit("/")) + 1, logoSerial.length() - logoSerial.findRev(QString::fromLocal8Bit("/"))).toInt();
            int month = logoSerial.left(logoSerial.find(QString::fromLocal8Bit("/"))).toInt();   
            inStream >> currentString;
            inStream >> currentString;
            inStream >> currentString;
            logoSerial = logoSerial + QString::fromLocal8Bit(" ") + currentString;
        } 
        else if (currentString == QString::fromLocal8Bit("NUMBER_OF_FIELDS"))
        {
            inStream >> currentString;
            numFields = currentString.toInt();
            numFieldsStr = currentString;
        }
        else if (currentString == QString::fromLocal8Bit("BEGIN_DATA_FORMAT"))
        {
            dataNames = new QString[numFields + 6];
            int i = 0;
            highSpec = 0;
            while (i < numFields)
            {
                inStream >> dataNames[i];
                if (dataNames[i].left(2) == QString::fromLocal8Bit("nm"))
                {
                    if (!spec)
                    {
                        spec=true;
                        lowSpec = dataNames[i].right(3).toInt();
                    }
                    else if (highSpec < dataNames[i].right(3).toInt())
                        highSpec = dataNames[i].right(3).toInt();
                    specBands++;
                }
                i++; 
            } 
            if (spec)
            {
                for (i=0; i < 6; i++)
                {
                    dataNames[i + numFields] = newDataNames[i];
                }
                numFields = numFields + 6;
            }
        }
    }
    
    numFields = numFields - 1;
    
    LCMSHANDLE it8 = cmsIT8Alloc();
    cmsIT8SetPropertyStr(it8, "DESCRIPTOR", (const char *) CCFilename.toLocal8Bit());
    cmsIT8SetSheetType(it8, "LCMS");
    cmsIT8SetPropertyStr(it8, "CREATED", (const char *) logoSerial.toLocal8Bit());
    
    if (CCFilename.left(7) == QString::fromLocal8Bit("CMP Dig"))
    {       
        cmsIT8SetPropertyStr(it8, "ORIGINATOR", (const char *) "LProf Reference File Installer");
        // FIXME need to parse out serial number from file name
        cmsIT8SetPropertyStr(it8, "SERIAL", (const char *) CCFilename.mid(24, 6).toLocal8Bit());
        cmsIT8SetPropertyStr(it8, "MANUFACTURER", (const char *) "CMP");
    }
    else
    {
        cmsIT8SetPropertyStr(it8, "ORIGINATOR", (const char *) "LProf Reference File Installer");
        // FIXME to create a serial 
        cmsIT8SetPropertyStr(it8, "SERIAL", (const char *) logoSerial.toLocal8Bit());
        cmsIT8SetPropertyStr(it8, "MANUFACTURER", (const char *) "X-Rite/GretagMacbeth");
    }
    
    cmsIT8SetPropertyDbl(it8, "SPECTRAL_BANDS", double (specBands));
    spectral.spec_n = specBands;
    cmsIT8SetPropertyDbl(it8, "SPECTRAL_START_NM", double (lowSpec));
    spectral.spec_wl_short = (float) lowSpec;
    cmsIT8SetPropertyDbl(it8, "SPECTRAL_END_NM", double (highSpec));
    spectral.spec_wl_long = (float) highSpec;
    
    numFieldsStr = numFieldsStr.setNum(numFields);
    cmsIT8SetPropertyStr(it8, "NUMBER_OF_FIELDS", numFieldsStr.toLocal8Bit());
    cmsIT8SetPropertyStr(it8, "NUMBER_OF_SETS", numSetsStr.toLocal8Bit());
    
    totalFields = numFields;
    
    bool startSpec = true;
    bool startRow;
    int count, firstNM = 0;
    
    
    for (int k=1; k <= totalFields; k++)
    {
        cmsIT8SetDataFormat(it8, k - 1, dataNames[k].toLocal8Bit());
        if (dataNames[k].left(2) == QString::fromLocal8Bit("nm") && startSpec)
        {
            startSpec = false;
            firstNM = k - 1;
        }
    }
    
    
    startSpec = true;
    
    xsp2cie *sp2cie;
    // Create a spectral conversion object
    if ((sp2cie = new_xsp2cie (icxIT_D50,  NULL, icxOT_CIE_1931_2, NULL, icSigXYZData)) == NULL)
    {
        qDebug ("Creation of spectral conversion object failed");
    }
    else
    {
        double XYZ[3];
        cmsCIExyY wp;
        cmsCIEXYZ WhitePoint;
        cmsCIEXYZ xyz;
        cmsCIELab Lab;
        bool firstRow = true;
        spectral.norm = 100.0;
        double factor;
        for (int i=0; i < numSets; i++)
        {
            for (int k=0; k < totalFields; k++)
            {
                QString sampleID;
                if (k == 0)
                {
                    inStream >> sampleID;
                    inStream >> currentString;
                    cmsIT8SetDataRowCol(it8, i, k, currentString.toLocal8Bit());
                }
                else if (spec)
                {
                    if (dataNames[k + 1].left(2) == QString::fromLocal8Bit("nm"))
                    {
                        startRow = true;
                        count = 0;
                        inStream >> measurement;
                        cmsIT8SetDataRowColDbl(it8, i, k, measurement * 100.0);
                        spectral.spec[k - firstNM] = measurement * 100.0;
                    }
                    else if ((dataNames[k + 1].left(3) == QString::fromLocal8Bit("XYZ") || dataNames[k + 1].left(3) == QString::fromLocal8Bit("LAB")))
                    {
                        double value;
                        if (dataNames[k + 1] == QString::fromLocal8Bit("XYZ_X"))
                        {
                            sp2cie->convert (sp2cie, XYZ, &spectral);
                            value = XYZ[0] * 100.0;
                        }
                        else if (dataNames[k + 1] == QString::fromLocal8Bit("XYZ_Y"))
                            value = XYZ[1] * 100.0;
                        else if (dataNames[k + 1] == QString::fromLocal8Bit("XYZ_Z"))
                            value = XYZ[2] * 100.0;
                        else if (dataNames[k + 1] == QString::fromLocal8Bit("LAB_L"))
                        {
                            xyz.X = XYZ[0];
                            xyz.Y = XYZ[1];
                            xyz.Z = XYZ[2];
                            cmsWhitePointFromTemp(5000, &wp);
                            cmsxyY2XYZ(&WhitePoint, &wp);
                            cmsXYZ2Lab(&WhitePoint, &Lab, &xyz);
                            value = Lab.L;
                        }
                        else if (dataNames[k + 1] == QString::fromLocal8Bit("LAB_A"))
                            value = Lab.a;
                        else if (dataNames[k + 1] == QString::fromLocal8Bit("LAB_B"))
                            value = Lab.b;
                        cmsIT8SetDataRowColDbl(it8, i, k, value);
                    }
                    else if (dataNames[k + 1].left(3) == QString::fromLocal8Bit("RGB") || dataNames[k + 1].left(3) == QString::fromLocal8Bit("CMY"))
                    // just passthrough RGB and CMY(K) data.
                    { 
                        inStream >> measurement;
                        cmsIT8SetDataRowColDbl(it8, i, k, measurement);
                    } 
                }
                else if (dataNames[k + 1].left(3) == QString::fromLocal8Bit("XYZ") || dataNames[k + 1].left(3) == QString::fromLocal8Bit("LAB") || 
                         dataNames[k + 1].left(3) == QString::fromLocal8Bit("RGB") || dataNames[k + 1].left(3) == QString::fromLocal8Bit("CMY"))
                { 
                    // This is a CIE based logo file just output the existing data.
                    inStream >> measurement;
                    cmsIT8SetDataRowColDbl(it8, i, k, measurement);
                } 
            }
            firstRow = false;
        }
    }

    sp2cie->del (sp2cie);
    cmsIT8SaveToFile(it8, (const char *) fileName.toLocal8Bit());
    cmsIT8Free(it8);
}

void InstallRefFile::ColorCheckerConvert()
{
    // Added support for colorchecker-SG and DC targets.
    // Also support other logo targets such as the i1 scanner 1.4 target
    // Assumes both ArgyllCMS files are in the lprof application directory:
    //    lprofApp -> applicationDirPath()   On Windows or in the path on
    // Other systems
    
    // *Fix-me request: Sometimes (or usually when there is no reference file installed),
    //  the user needs to hit the "install" button twice in order for the new target to
    //  be created.
    
    // this is now obsolete and it has been replaced by logoConvert()
    // This removes the need to use logo2cgats and spec2cie from argyll
    
    // Grab basename of Colorchecker file.
    QString CCFilename;
    
    int startOfFileName;
    startOfFileName = TargetSelector->getFilename().findRev(QString::fromLocal8Bit("/"), -1);
    CCFilename = TargetSelector->getFilename();		
    CCFilename.remove(0, startOfFileName + 1);
    CCFilename.remove(CCFilename.findRev(QString::fromLocal8Bit("."), -1), 4);

    // Save current dir and switch into temp dir
    QString currPath = QDir::currentDirPath();
    QDir::setCurrent(dirs.temp_dir);
        
    // Utilize logo2cgats file.
    // build logo2cgats command and run it
    QString logo2cgats = QString::fromLocal8Bit("\"") + getAppExecDir() + QString::fromLocal8Bit("/logo2cgatslprof") + QString::fromLocal8Bit("\"") + QString::fromLocal8Bit(" \"") + TargetSelector->getFilename() + QString::fromLocal8Bit("\"") + QString::fromLocal8Bit(" temp");
    system(logo2cgats.toLocal8Bit());
    
    // Utilize spec2cie file.
    // build spec2cie command line and run it 
    QString spec2cie = QString::fromLocal8Bit("\"") + getAppExecDir() + QString::fromLocal8Bit("/spec2cielprof") + QString::fromLocal8Bit("\"") 
            + QString::fromLocal8Bit(" temp.ti3 temp2.ti3");
    system(spec2cie.toLocal8Bit());
    
    QString fileName = dirs.ref_dir + QString::fromLocal8Bit("/") + CCFilename + QString::fromLocal8Bit(" CGATS.txt");
   
        
    CleanKEYWORDS(QString::fromLocal8Bit("temp2.ti3"), fileName);
    
    // Save new target with "CGATS" label.
    files.items.targetFile = fileName;
    
    // Remove Temporary Files.
    QFile eraseTempFile(QString::fromLocal8Bit("temp.ti3"));
    // eraseTempFile.remove();
    QFile eraseTempFile2(QString::fromLocal8Bit("temp2.ti3"));
    // eraseTempFile2.remove();
            
    // restore current directory
    QDir::setCurrent(currPath);
    
    // Modify fields in reference file so that this shows up correctly in UI
    LCMSHANDLE hIT8 = cmsIT8LoadFromFile((const char *) files.items.targetFile.toLocal8Bit());
    cmsIT8SetPropertyStr(hIT8, "ORIGINATOR", (const char *) "LProf Reference File Installer");
    if (LogoDescriptor == QString::fromLocal8Bit(""))
        LogoDescriptor = QString::fromLocal8Bit("Unknown - no decriptor found");
    if (LogoSerial == QString::fromLocal8Bit(""))
        LogoSerial = QString::fromLocal8Bit("Unknown - no serial found");
    cmsIT8SetPropertyStr(hIT8, "DESCRIPTOR", (const char *) LogoDescriptor.toLocal8Bit());
    cmsIT8SetPropertyStr(hIT8, "SERIAL", (const char *) LogoSerial.toLocal8Bit());
    cmsIT8SetPropertyStr(hIT8, "CREATED", (const char *) LogoSerial.toLocal8Bit());
    cmsIT8SetPropertyStr(hIT8, "MANUFACTURER", (const char *) "X-Rite");
    cmsIT8SaveToFile(hIT8, (const char *) files.items.targetFile.toLocal8Bit());
    
    // QDir::cleanDirPath( files.items.targetFile );
    logoConvert();
}


bool InstallRefFile::refNotToOld()
{
    // qDebug("checkDescription");
    
    if (refToOld)
    {
        QMessageBox mb( QTranslator::tr("Reference File is Old"),
                        QTranslator::tr("This reference file is old.  "
                                "Targets need to be replaced every two to three years.  "
                                "This reference file is at least 3 years old.  "
                                "\n\nInstall this reference file anyway?"),
                                QMessageBox::Warning,
                                QMessageBox::Yes,
                                QMessageBox::No | QMessageBox::Default,
                                Qt::NoButton );
        mb.setButtonText( QMessageBox::Yes, QTranslator::tr("Yes"));
        mb.setButtonText( QMessageBox::No, QTranslator::tr("No"));
        switch( mb.exec() )
        {
            case QMessageBox::Yes:
                return TRUE;
                break;
            case QMessageBox::No:
                return FALSE;
                break;
        }
    }
    else
        return TRUE;
}
