#include "transferfunctioneditor.h"

TransferFunctionEditor::TransferFunctionEditor(QWidget *parent) :
    QWidget(parent)
{

    histogram = new int[256];

    for(int i = 0; i < 256; i++)
    {
        histogram[i] = 0;
    }
    histoMax = 1;



    this->setFixedSize(256,256);

    red = true;
    green = true;
    blue = true;
    alpha = true;

    temp = 3;

    trans = new uchar[4*256];
    this->reset();

}

void TransferFunctionEditor::setHistogram(int *his){
    histogram = his;

    histoMax = 0;
    for(int i = 0; i < 256; i++)
    {

        histoMax = qMax(histoMax,histogram[i]);
    }
}

void TransferFunctionEditor::setTransferFunction(uchar *trans){
    this->trans = trans;
}


uchar* TransferFunctionEditor::getTransferFunctin(){
    return trans;
}


TransferFunctionEditor::~TransferFunctionEditor()
{

}


void TransferFunctionEditor::paintEvent(QPaintEvent *event){
    QPainter painter(this);

    QPen pen(QColor(100,100,100,100));

    for(int i = 0; i < 256; i++)
    {
        painter.setPen(pen);
        int top = histogram[i]*256/histoMax;
        //qDebug()<<i<<top;
        painter.drawLine(i,256,i,256-top);
    }

    if(red){
        pen = QPen(QColor(255,0,0,255));
        painter.setPen(pen);
        for(int i = 0; i < 4*255; i+=4){
            painter.drawLine(i/4,256-trans[i],i/4+1,256-trans[i+4]);
        }
    }

    if(green){
        pen = QPen(QColor(0,255,0,255));
        painter.setPen(pen);
        for(int i = 1; i < 4*255; i+=4){
            painter.drawLine(i/4,256-trans[i],i/4+1,256-trans[i+4]);
        }
    }

    if(blue){
        pen = QPen(QColor(0,0,255,255));
        painter.setPen(pen);
        for(int i = 2; i < 4*255; i+=4){
            painter.drawLine(i/4,256-trans[i],i/4+1,256-trans[i+4]);
        }
    }

    if(alpha){
        pen = QPen(QColor(0,0,0,255));
        painter.setPen(pen);
        for(int i = 3; i < 4*255; i+=4){
            painter.drawLine(i/4,256-trans[i],i/4+1,256-trans[i+4]);
        }
    }

}

void TransferFunctionEditor::paintRed(bool paint){
    this->red =paint;
    this->repaint();
}

void TransferFunctionEditor::paintGreen(bool paint){
    this->green =paint;
    this->repaint();
}
void TransferFunctionEditor::paintBlue(bool paint){
    this->blue =paint;
    this->repaint();
}
void TransferFunctionEditor::paintAlpha(bool paint){
    this->alpha =paint;
    this->repaint();
}


void TransferFunctionEditor::save(){
    QString fn = QFileDialog::getSaveFileName(NULL, tr("Save Transfer Function..."),
                                              QString("D:\\Projekte\\GraPa\\A3"), tr("TransferFunction (*.tf )"));
    if(fn.isEmpty())
        return;
    qDebug()<<"Save"<< fn;

    QFile file(fn);
    if(!file.open(QIODevice::WriteOnly)) {
        QMessageBox::information(0, "error", file.errorString());
    }
    qDebug()<<*(trans+5);
    file.write((char*)this->trans,4*256);
    file.close();
}

void TransferFunctionEditor::load(){
    QString fn = QFileDialog::getOpenFileName(NULL, tr("Open Transfer Function..."),
                                              QString("D:\\Projekte\\GraPa\\A3"), tr("TransferFunction (*.tf )"));
    if(fn.isEmpty())
        return;
    qDebug()<<"Open"<< fn;

    QFile file(fn);
    if(!file.open(QIODevice::ReadOnly)) {
        QMessageBox::information(0, "error", file.errorString());
    }
    QByteArray data = file.readAll();
   // trans = reinterpret_cast<uchar*>(data.data());

    for(int i = 0; i < 4*256; i+=1){
        trans[i] = data.at(i);
    }

    file.close();

    emit dataChanged(trans);
    this->repaint();
}
void TransferFunctionEditor::reset(){

    for(int i = 0; i < 256; i+=1){
        int index = i*4;
        if(red) trans[index] = i;
        if(green) trans[index+1] = i;
        if(blue)trans[index+2] = i;
        if(alpha) trans[index+3] = i;
    }
    emit dataChanged(trans);
    this->repaint();
    qDebug()<<"reset";
}
void TransferFunctionEditor::smooth(){
    uchar* smothed = new uchar[4*256];

    qDebug()<<"smooth";


    for(int i = 0; i < 1024; i++){
        if(i < 1020 && (red && i % 4 == 0
                        ||green && i % 4 == 1
                        ||blue && i % 4 == 2
                        ||alpha && i % 4 == 3)){
            int im2=i-2*4;
            for(;im2<0;im2+=4);

            int im1=i-4;
            for(;im1<0;im1+=4);

            int ip1=i+4;//1020
            for(;ip1>1023;ip1-=4);

            int ip2=i+2*4;
            for(;ip2>1023;ip2-=4);

            //            if(i % 4 == 0) qDebug()<<"r"<<im2<<im1<<i<<ip1<<ip2;
            //            if(i % 4 == 1) qDebug()<<"g"<<im2<<im1<<i<<ip1<<ip2;
            //            if(i % 4 == 2) qDebug()<<"b"<<im2<<im1<<i<<ip1<<ip2;
            //            if(i % 4 == 3) qDebug()<<"a"<<im2<<im1<<i<<ip1<<ip2;

            smothed[i] = (trans[im2]+2*trans[im1]+4*trans[i]+2*trans[ip1]+trans[ip2])/10;
            //qDebug()<<trans[i]<<"->"<<smothed[i];
        } else{
            smothed[i] = trans[i];
        }

    }

    trans = smothed;
    emit dataChanged(trans);
    this->repaint();
}

void TransferFunctionEditor::mousePressEvent(QMouseEvent *event ){
    // qDebug()<<event->pos().x()<< event->pos().y();
    int value = 255 - event->pos().y();
    if(red){
        trans[event->pos().x()*4] = value;
    }
    if(green){
        trans[event->pos().x()*4+1] = value;
    }
    if(blue){
        trans[event->pos().x()*4+2] = value;
    }
    if(alpha){
        trans[event->pos().x()*4+3] = value;
    }


    for(int i = 1; i < 10; i++){
        float step = 1.0/pow(1.1,i);
        if(red){
            int pos = event->pos().x()*4;
            trans[pos + 4*i ] = trans[pos + 4*i]+ (value- trans[pos + 4*i])*step;
            trans[pos - 4*i ] = trans[pos - 4*i]+ (value- trans[pos - 4*i])*step;
        }
        if(green){
            int pos = event->pos().x()*4+1;
            trans[pos + 4*i ] = trans[pos + 4*i]+ (value- trans[pos + 4*i])*step;
            trans[pos - 4*i ] = trans[pos - 4*i]+ (value- trans[pos - 4*i])*step;
        }
        if(blue){
            int pos = event->pos().x()*4+2;
            trans[pos + 4*i ] = trans[pos + 4*i]+ (value- trans[pos + 4*i])*step;
            trans[pos - 4*i ] = trans[pos - 4*i]+ (value- trans[pos - 4*i])*step;
        }
        if(alpha){
            int pos = event->pos().x()*4+3;
            trans[pos + 4*i ] = trans[pos + 4*i]+ (value- trans[pos + 4*i])*step;
            trans[pos - 4*i ] = trans[pos - 4*i]+ (value- trans[pos - 4*i])*step;
        }
    }
    emit dataChanged(trans);
    this->repaint();

}
