#include "bitmaplist.h"
#include "bitmaplistitem.h"
#include "bitmapwidget.h"
#include <qfiledialog.h>
#include <qimage.h>
#include <qintdict.h>
#include <qtextstream.h>
#include <kfiledialog.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kapp.h>

int QColorList::compareItems(Item item1, Item item2)
{
    QColor *c1 = (QColor *)item1;
    QColor *c2 = (QColor *)item2;
    if(c1->rgb() > c2->rgb())
        return(1);
    else if (c1->rgb() < c2->rgb())
        return(-1);
    return(0);
}


KPBitmapList::KPBitmapList(const QString &defPrefix, QWidget *parent,
                           const char *name)
    : QListBox(parent, name)
{
    bmpList.setAutoDelete(true);
    prefixStr = defPrefix;
    bmpPreview = NULL;
    connect(this, SIGNAL(selected(int)), SLOT(slotSelected(int)));
}

void KPBitmapList::insertBitmap(const QBitmap *bitmap, const QColor *color)
{
    KPBitmapListItem *i;
    // can't use QColor::name() because of the # (this can go in headers).
    if(color){
        QString colorName;
        colorName.sprintf("%.2x%.2x%.2x", color->red(), color->green(),
                          color->blue());
        i = new KPBitmapListItem(this, prefixStr+colorName, *color);
    }
    else
        i = new KPBitmapListItem(this, prefixStr + i18n("mask"), Qt::black);
    bmpList.append(bitmap);
}

void KPBitmapList::setPrefix(const QString &)
{
    ;
}

void KPBitmapList::reset()
{
    clear();
    if(bmpPreview)
        bmpPreview->reset();
    bmpList.clear();
    emit saveEnabled(false);
    emit closeEnabled(false);

}

void KPBitmapList::slotSelected(int index)
{
    if(bmpPreview)
        bmpPreview->setBitmap(bmpList.at(index));
}


void KPBitmapList::saveCurrentBitmap()
{
    QString fileStr = QFileDialog::getSaveFileName(QString::null,
                                                   i18n("X Bitmap (*.xbm)"));
    if(!fileStr.isEmpty()){
        QApplication::setOverrideCursor(waitCursor);
        if(!bmpList.at(currentItem())->save(fileStr, "XBM"))
            KMessageBox::error(this, i18n("Unable to save bitmap!"));
        else
            emit message(i18n("Single bitmap saved."));
        QApplication::restoreOverrideCursor();
    }
}

void KPBitmapList::saveCHeader()
{
    QString fileStr = QFileDialog::getSaveFileName(QString::null,
                                                   i18n("C++ Header (*.h)"));
    if(!fileStr.isEmpty()){
        QFile file(fileStr);
        QImage image;
        if(file.open(IO_ReadWrite)){
            QApplication::setOverrideCursor(waitCursor);
            QImageIO io(&file, "XBM");
            QTextStream stream(&file);
            unsigned int i, totalFiles = bmpList.count();

            stream << "/* Image bits processed by KPixmap2Bitmaps */\n\n";
            for(i = 0; i < totalFiles; ++i){
                image = bmpList.at(i)->convertToImage();
                io.setImage(image);
                io.setFileName(text(i)); // just sets XBM name
                if(!io.write()){
                    KMessageBox::error(this, i18n("Unable to C Header!"));
                    emit setProgress(0);
                    QApplication::restoreOverrideCursor();
                    file.close();
                    return;
                }
                emit setProgress((int)(i/(float)totalFiles*100));
                kapp->processEvents();
                stream << "\n";
            }
            file.close();
            QApplication::restoreOverrideCursor();
            emit setProgress(0);
            emit message(i18n("C Header saved."));
        }
        else
            KMessageBox::error(this, i18n("Unable to C Header!"));
    }
}

void KPBitmapList::savePointArray()
{
    QString fileStr = QFileDialog::getSaveFileName(QString::null,
                                                   i18n("C++ Header (*.h)"));
    if(fileStr.isEmpty())
        return;
    QFile file(fileStr);
    if(!file.open(IO_WriteOnly))
        return;
    QTextStream stream(&file);
    unsigned int i, totalFiles = bmpList.count();
    int x, y, count;
    bool wrotePoint;
    QColor color;

    QApplication::setOverrideCursor(waitCursor);
    stream << "/* Image bits processed by KPixmap2Bitmaps */\n";
    for(i=0; i < totalFiles; ++i){
        QBitmap *bitmap = bmpList.at(i);
        QImage image = bitmap->convertToImage();
        stream << "\nstatic QCOORD " << text(i) << "[] = {";
        count = 0;
        for(y=0, wrotePoint=false; y < image.height(); ++y){
            for(x=0; x < image.width(); ++x){
                color.setRgb(image.pixel(x, y));
                if(color != Qt::color0){
                    if(wrotePoint)
                        stream << ", " << x << "," << y;
                    else
                        stream << x << "," << y;
                    wrotePoint = true;
                    ++count;
                    if(count > 7){
                        stream << "\n";
                        count = 0;
                    }
                }
            }
            emit setProgress((int)(i/(float)totalFiles*100));
            kapp->processEvents();
        }
        stream << "};\n";
    }
    file.close();
    emit message(i18n("QCOORD arrays saved"));
    emit setProgress(0);
    QApplication::restoreOverrideCursor();
}
                    
void KPBitmapList::saveAll()
{
    QString dirStr = QFileDialog::getExistingDirectory();
    unsigned int totalFiles = bmpList.count();
    if(dirStr && count() != 0){
        unsigned int i;
        QApplication::setOverrideCursor(waitCursor);
        for(i = 0; i < totalFiles; ++i){
            if(!bmpList.at(i)->save(dirStr+"/"+text(i)+".xbm", "XBM")){
                KMessageBox::error(this, i18n("Unable to save bitmap!"));
                emit setProgress(0);
                QApplication::restoreOverrideCursor();
                return;
            }
            emit setProgress((int)(i/(float)totalFiles*100));
            kapp->processEvents();
        }
    }
    emit message(i18n("All bitmaps saved"));
    emit setProgress(0);
    QApplication::restoreOverrideCursor();
}

void KPBitmapList::load()
{
    loadFile(QFileDialog::getOpenFileName());
}

void KPBitmapList::loadFile(const QString &fileStr)
{
    if(fileStr.isEmpty())
        return;

    QPixmap pix(fileStr);
    if(pix.isNull()){
        emit message(i18n("Invalid image file"));
        return;
    }
    QImage mask, image = pix.convertToImage();
    QRgb *maskCT = 0;
    if(image.depth() != 32)
        image.convertDepth(32, AutoColor | ThresholdDither | AvoidDither);

    // we maintain two items, a dict of images with the RGB as the key, and
    // a sorted list of color entries
    QIntDict<QImage> imageDict;
    QColorList colorList;

    imageDict.setAutoDelete(true);
    colorList.setAutoDelete(true);

    reset();
    QApplication::setOverrideCursor(waitCursor);
    int x, y, val, oldVal=0;
    emit message(i18n("Separating and sorting color entries"));
    if(pix.mask()){
        insertBitmap(new QBitmap(*pix.mask()), NULL);
        mask = pix.mask()->convertToImage();
        maskCT = mask.colorTable();
    }
    QColor color;
    for(y=0; y < image.height(); ++y){
        for(x=0; x < image.width(); ++x){
            if(mask.isNull() || maskCT[mask.pixelIndex(x, y)] == color1.rgb()){
                color.setRgb(image.pixel(x, y));
                QImage *plane = imageDict.find((unsigned int)color.rgb());
                if(!plane){
                    plane = new QImage(image.width(), image.height(), 1, 0,
                                       QImage::systemBitOrder());
                    plane->fill(0);
                    imageDict.insert((unsigned int)color.rgb(), plane);
                    colorList.inSort(new QColor(color));
                }
                plane->setPixel(x, y, 1);
            }
        }
        val = (int)(y/(float)image.height()*100);
        if(val != oldVal){
            oldVal = val;
            emit setProgress(val);
            kapp->processEvents();
        }
    }
    QListIterator<QColor> it(colorList);
    while(it.current()){
        QBitmap *bmp = new QBitmap;
        if(imageDict.find((unsigned int)it.current()->rgb())){
            bmp->convertFromImage(*imageDict.find((unsigned int)(it.current())->rgb()));
            QColor *color = it.current();
            insertBitmap(bmp, color);
        }
        else
            warning("Cannot find color");
        ++it;
    }
    QString str;
    str.sprintf("%d", count());
    emit message(i18n("Image loaded with ") + str + i18n(" colors"));
    emit setProgress(0);

    if(count()){
        setCurrentItem(0);
        slotSelected(0);
        emit saveEnabled(true);
        emit closeEnabled(true);
    }
    QApplication::restoreOverrideCursor();
    return;
}



#include "bitmaplist.moc"

    
