#include "ephoto.h"
#include "cfg.h"
#include "tools.h"
#include <QComboBox>
#include <QFileDialog>
#include <QImageReader>
#include <QLineEdit>
#include <QMessageBox>
#include <QPainter>
#include <QSpinBox>

EPhoto *EPhoto::create(const QString &file, PageListItem *pageItem, EBase *multiWin) {
    QImageReader reader(file);
    QImage img = reader.read();
    if(img.isNull()) {
        QMessageBox::critical(gMainWin, "Image Error", Tools::readErrStr(reader.error())+": "+reader.errorString()+"\n"+file);
        return nullptr;
    }
    QFileInfo info(file);
    return new EPhoto(img, info.absolutePath(), info.fileName(), pageItem, multiWin);
}
EPhoto *EPhoto::create(const QJsonObject &json, PageListItem *pageItem, EBase *multiWin) {
    auto widget = json["widget"];
    auto dir = widget["path"].toString();
    auto name = widget["file"].toString();
    if(! QFileInfo(dir).isDir()) dir = pageItem->mPageDir;
    QString file = dir + "/" + name;
    QFileInfo fileInfo(file);
    if(! fileInfo.isFile()) {
        QString file2 = dir + "/" + widget["yuanshi_file"].toString();
        if(QFileInfo(file2).isFile()) QFile::rename(file2, file);
        else if(QFileInfo(file2 = widget["computer_pic_file"].toString()).isFile()) QFile::copy(file2, file);
        else if(QFileInfo(file2 = dir + "/card_"+name).isFile()) QFile::rename(file2, file);
        else return nullptr;
    }
    auto img = QImage(file);
    if(img.isNull()) return nullptr;
    auto ins = new EPhoto(img, dir, name, pageItem, multiWin);
    ins->setBaseAttr(json);
    auto play = json["play"];
    ins->mDuration = play["playDuration"].toInt();
    ins->mEnterStyle = play["enterStyle"].toInt();
    ins->mEnterDuration = play["enterDuration"].toInt();
    return ins;
}

EPhoto::EPhoto(const QImage &img, const QString &dir, const QString &name, PageListItem *pageItem, EBase *multiWin) : EBase(multiWin), img(img), mDir(dir), mName(name), mPageItem(pageItem) {
    mType = EBase::Photo;
    scaleImgIfNeed();
}
QJsonObject EPhoto::attrJson() const {
    QJsonObject oRoot;
    addBaseAttr(oRoot);
    oRoot["elementType"] = "Photo";
    oRoot["widget"] = QJsonObject{
        {"path", mDir},
        {"file", mName}
    };
    oRoot["play"] = QJsonObject{
        {"playDuration", mDuration},
        {"playTimes", 1},
        {"enterStyle", mEnterStyle},
        {"enterDuration", mEnterDuration}
    };
    return oRoot;
}
void EPhoto::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
    painter->drawImage(innerRect(), img);
    EBase::paint(painter, option, widget);
}
void EPhoto::freeFiles() {
    if(img.isNull()) return;
    img = QImage();
}
void EPhoto::loadFiles() {
    if(! img.isNull()) return;
    if(! QFileInfo::exists(mDir + "/" + mName)) return;
    img = QImage(mDir + "/" + mName);
    if(gProgItem->mMaxWidth) {
        QImage square(gProgItem->mMaxWidth, gProgItem->mHeight*gProgItem->mSplitWidths.size(), QImage::Format_ARGB32);
        QPainter painter(&square);
        QRectF rect(x(), y(), mWidth, mHeight);
        painter.drawImage(rect, img);
        auto end = gProgItem->mSplitWidths.size() - 1;
        for(int i=0; i<end; i++) {
            rect.moveTo(rect.x() - gProgItem->mSplitWidths[i], rect.y() + gProgItem->mHeight);
            painter.drawImage(rect, img);
        }
        square.save(mDir + "/" + mName+"-square.png", "PNG");
    }
}
bool EPhoto::save(const QString &pageDir) {
    QString newName = mName;
    QString newFile = pageDir + "/" + newName;
    if(QFileInfo::exists(newFile)) {
        newFile = Tools::addSufix(newFile);
        newName = QFileInfo(newFile).fileName();
    }
    QString oldFile = mDir + PAGEDEL_SUFFIX + "/" + mName;
    if(QFileInfo::exists(oldFile)) QFile(oldFile).copy(newFile);
    else if(pageDir!=mDir && QFileInfo::exists(oldFile = mDir + "/" + mName)) QFile(oldFile).copy(newFile);
    else if(QFileInfo::exists(pageDir + "/" + mName)) newName = mName;
    mDir = pageDir;
    mName = newName;
    return true;
}

QWidget* EPhoto::attrWgt() {
    auto wgtAttr = new QWidget();
    auto vBox = new QVBoxLayout(wgtAttr);
    vBox->setContentsMargins(6, 0, 6, 0);
    if(mMultiWin!=nullptr) vBox->setSpacing(3);

    addBaseAttrWgt(vBox);

    auto hBox = new QHBoxLayout();
    hBox->addWidget(new QLabel(tr("Basic Properties")));

    auto line = new QFrame();
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);
    hBox->addWidget(line, 1);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("File")));

    auto fdFile = new QLineEdit(mName);
    fdFile->setReadOnly(true);
    hBox->addWidget(fdFile);

    auto bnSelectFile = new QPushButton("...");
    bnSelectFile->setFixedWidth(30);
    bnSelectFile->setObjectName("bnSelectFile");
    connect(bnSelectFile, &QPushButton::clicked, this, [this, fdFile] {
        QString home = mDir.startsWith(gProgItem->mProgDir) ? gFileHome : mDir;
        QString file = QFileDialog::getOpenFileName(gMainWin, tr("Select File"), home, EPhoto::filters());
        if(file.isEmpty()) return;
        QImageReader reader(file);
        QImage aimg = reader.read();
        if(aimg.isNull()) {
            QMessageBox::critical(gMainWin, tr("Image Read Error"), Tools::readErrStr(reader.error())+": "+reader.errorString()+"\n"+file);
            return;
        }
        img = aimg;
        QFileInfo info(file);
        mDir = info.absolutePath();
        gFileHome = mDir;
        mName = info.fileName();
        scaleImgIfNeed();
        fdFile->setText(mName);
    });
    hBox->addWidget(bnSelectFile);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addWidget(new QLabel(tr("Play Properties")));

    line = new QFrame();
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);
    hBox->addWidget(line, 1);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("Play Duration")));

    auto fdDuration = new QSpinBox();
    fdDuration->setRange(1, 99999);
    fdDuration->setValue(mDuration);
    hBox->addWidget(fdDuration);

    hBox->addWidget(new QLabel(tr("s")));
    hBox->addStretch();

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("Enter Style")));

    auto wEnterStyle = new QComboBox();
    wEnterStyle->addItem(tr("None"));
    wEnterStyle->addItem(tr("Alpha_In"));
    wEnterStyle->addItem(tr("Moving to left"));
    wEnterStyle->addItem(tr("Moving to right"));
    wEnterStyle->addItem(tr("Moving to top"));
    wEnterStyle->addItem(tr("Move to bottom"));
    wEnterStyle->addItem(tr("Zoom in"));
    wEnterStyle->addItem(tr("Zoom in to left_bottom"));
    wEnterStyle->addItem(tr("Zoom in to left_top"));
    wEnterStyle->addItem(tr("Zoom in to right_top"));
    wEnterStyle->addItem(tr("Zoom in to right bottom"));
    wEnterStyle->addItem(tr("Rotate to right"));
    wEnterStyle->addItem(tr("Rotate to left"));
    wEnterStyle->setCurrentIndex(mEnterStyle);
    connect(wEnterStyle, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int value) {
        mEnterStyle = value;
    });
    hBox->addWidget(wEnterStyle);
    hBox->addStretch();

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("Enter Duration")));

    auto fdEnterDuration = new QSpinBox();
    fdEnterDuration->setRange(1, 99999);
    fdEnterDuration->setValue(mEnterDuration);
    connect(fdDuration, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, fdEnterDuration](int value){
        mDuration = value;
        if(mEnterDuration > value) {
            mEnterDuration = value;
            fdEnterDuration->setValue(value);
        }
    });
    connect(fdEnterDuration, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, fdDuration](int value){
        mEnterDuration = value;
        if(mDuration < value) {
            mDuration = value;
            fdDuration->setValue(value);
        }
    });
    hBox->addWidget(fdEnterDuration);

    hBox->addWidget(new QLabel(tr("s")));
    hBox->addStretch();

    vBox->addLayout(hBox);
    vBox->addStretch();
    return wgtAttr;
}

void EPhoto::scaleImgIfNeed() {
    if(img.width() > 4096 || img.height() > 4096) {
        if(img.width() > img.height()) img = img.scaledToWidth(3840, Qt::SmoothTransformation);
        else img = img.scaledToHeight(3840, Qt::SmoothTransformation);
        if(mName.endsWith(".jpg", Qt::CaseInsensitive)) mName = mName.chopped(3)+"png";
        else if(mName.endsWith(".jpeg", Qt::CaseInsensitive)) mName = mName.chopped(4)+"png";
        mDir = mPageItem->mPageDir;
        QString save = mDir + "/" + mName;
        if(QFileInfo::exists(save)) {
            save = Tools::addSufix(save);
            mName = QFileInfo(save).fileName();
        }
        img.save(save);
    }
}
