/***************************************************************************
 *   Copyright (C) 2007-2011 by Vegeta                                     *
 *                                                                         *
 *   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 2 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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "renamefiles.h"
#include "coverdownload.h"

#include <QDir>
#include <QProcess>

renameFiles::renameFiles(QWidget *parent) : QWidget(parent), Counter(0) {
    ID3Process = new QProcess(this);
    connect (ID3Process, SIGNAL(finished(int)), this, SLOT(processID3Tags()));

    CoverDownloader = new CoverDownload(this);
    connect(CoverDownloader, SIGNAL(signal_allDownloadsFinished()), this, SLOT(allDownloadsFinished()));
    connect(CoverDownloader, SIGNAL(signal_addToErrorlog(QString)), this, SIGNAL(signal_addToErrorlog(QString)));
    connect(CoverDownloader, SIGNAL(signal_updateDownloadInfos()),  this, SLOT(updateDownloadInfos()));
}

renameFiles::~renameFiles(){
}

// *********************************************************************************************
// Process Tags of MP3 files
// *********************************************************************************************
void renameFiles::startRenaming(QList<QString> &Files, bool isRenameFiles, bool isRenameFolders, bool isDownload, QString renamePatternFolders, QString renamePatternFiles, int SearchEngine){
    Counter = 0;
    Skipped = 0;
    allFiles = Files;
    isAutorenameFiles   = isRenameFiles;
    isAutorenameFolders = isRenameFolders;
    isDownloadCovers    = isDownload;
    isCancelAllJobs     = false;
    folderTemplate      = renamePatternFolders;
    fileTemplate        = renamePatternFiles;
    searchEngine        = SearchEngine;

    folderRenamingInfo.currentPath.clear();
    folderRenamingInfo.renameFolderList.clear();
    readID3Tags();
}


// *********************************************************************************************
// Main loop
// *********************************************************************************************
void renameFiles::readID3Tags(){
    if (isCancelAllJobs) return;

    if (Counter < allFiles.size() && allFiles[Counter].endsWith(".mp3", Qt::CaseInsensitive)){

        // process id3v2 for all mp3 files
        if (isAutorenameFolders || isAutorenameFiles){
            currentFileName = allFiles[Counter];
            QStringList Parameter;
            Parameter << "-l" << currentFileName;
            ID3Process->start("id3v2", Parameter);
        }
        // Autorename is disabled so we only need to process one mp3 file in every folder
        else if (isDownloadCovers){
            QFileInfo tInfo1(currentFileName);
            QFileInfo tInfo2(allFiles[Counter]);

            if (tInfo1.absolutePath() != tInfo2.absolutePath()){
                currentFileName = allFiles[Counter];
                QStringList Parameter;
                Parameter << "-l" << currentFileName;
                ID3Process->start("id3v2", Parameter);
            } else {
                // Skip file
                ++Counter;
                readID3Tags();
                return;
            }
        }
    }
    else if (Counter < allFiles.size() && !allFiles[Counter].endsWith(".mp3", Qt::CaseInsensitive)){
        ++Counter;
        readID3Tags();
        return;
    }
    else if (Counter >= allFiles.size()){
        if (isDownloadCovers) CoverDownloader->startDownloads();
        else allDownloadsFinished();
    }

    ++Counter;
}


// *********************************************************************************************
// Process output of id3v2
// *********************************************************************************************
void renameFiles::processID3Tags(){
    if (isCancelAllJobs) return;

    int Track, Year;
    QString string = ID3Process->readAll();
    QString Song, Album, Artist, Genre;
    QFileInfo oldName(currentFileName);

    emit signal_updateDownloadInfos(tr("Processing ID3-Tags..."),  // QString Statustext,
                                    oldName.absolutePath().mid(oldName.absolutePath().lastIndexOf("/") + 1).left(30), // QString Foldertext,
                                    oldName.fileName(),        // QString Filetext,
                                    allFiles.size() - Counter, // int ToDo,
                                    0,                         // int Error,
                                    Skipped,                   // int Skipped,
                                    0,                         // int Gained,
                                    Counter,                   // int progressBarValue,
                                    allFiles.size(),           // int progressBarMax,
                                    false);                    // bool setDownloadIcon


    if (string.contains("id3v2 tag")){
        // ID3v2 tag info
        Track = searchRegExp("TRCK.*: (\\d+)\\n", string).toInt();
        Year = searchRegExp("TYER.*: (\\d+)\\n", string).toInt();
        Song = searchRegExp("TIT2.*: (.*)\\n", string);
        Album = searchRegExp("TALB.*: (.*)\\n", string);
        Artist = searchRegExp("TPE1.*: (.*)\\n", string);
        Genre = searchRegExp("TCON.*: (.*)\\(", string);
    } else if (string.contains("id3v1 tag")){
        // ID3v1 tag info
        Track = searchRegExp("Track: (\\d+)\\n", string).toInt();
        Year = searchRegExp("Year: (\\d+),", string).toInt();
        Song = searchRegExp("Title  : (.*)Artist:", string);
        Album = searchRegExp("Album  : (.*)Year:", string);
        Artist = searchRegExp("Artist: (.*)\n", string);
        Genre = searchRegExp("Genre: (.*)\\(", string);
    } else {
        // No ID3-Tags found
        emit signal_addToErrorlog(tr("<font color='red'>No ID3-Tag found -> skipped</font> :: %1<br>").arg(currentFileName));
        ++Skipped;
        readID3Tags();
        return;
    }


    if ((!Track > 0 && !Track < 50 && (folderTemplate.contains(tr("%Track")) || fileTemplate.contains(tr("%Track"))))  ||
        (!Year > 1900 && !Year < 2200 && (folderTemplate.contains(tr("%Year")) || fileTemplate.contains(tr("%Year")))) ||
        (Song.isEmpty() && (folderTemplate.contains(tr("%Song")) || fileTemplate.contains(tr("%Song"))))               ||
        (Album.isEmpty() && (folderTemplate.contains(tr("%Album")) || fileTemplate.contains(tr("%Album"))))            ||
        (Artist.isEmpty() && (folderTemplate.contains(tr("%Artist")) || fileTemplate.contains(tr("%Artist"))))         ||
        (Genre.isEmpty() && (folderTemplate.contains(tr("%Genre")) || fileTemplate.contains(tr("%Genre")))))
    {
        emit signal_addToErrorlog(tr("<font color='red'>Not all ID3-Tags found or not all tags are valid -> skipped</font> :: %1<br>").arg(currentFileName));
        readID3Tags();
        ++Skipped;
        return;
    }

    QString BadStrings = "(http|www|[@€%$§*_])";
    if (!searchRegExp(BadStrings, Song).isEmpty()   ||
        !searchRegExp(BadStrings, Album).isEmpty()  ||
        !searchRegExp(BadStrings, Artist).isEmpty() ||
        !searchRegExp(BadStrings, Genre).isEmpty())
    {
        emit signal_addToErrorlog(tr("<font color='red'>Found 'to ignore' pattern in ID3-Tags -> skipped</font> :: %1<br>").arg(currentFileName));
        readID3Tags();
        ++Skipped;
        return;
    }

    QString tmpfileTemplate = fileTemplate;
    tmpfileTemplate.replace(tr("%Track"),  QString::number(Track));
    tmpfileTemplate.replace(tr("%Year"),   QString::number(Year));
    tmpfileTemplate.replace(tr("%Song"),   Song);
    tmpfileTemplate.replace(tr("%Album"),  Album);
    tmpfileTemplate.replace(tr("%Artist"), Artist);
    tmpfileTemplate.replace(tr("%Genre"),  Genre);
    tmpfileTemplate.append(".mp3");

    if (isAutorenameFiles && oldName.fileName() != tmpfileTemplate) {
        bool val = QFile::rename(oldName.absoluteFilePath(), oldName.absolutePath() + "/" + tmpfileTemplate);
        if (!val) signal_addToErrorlog(tr("<font color='red'>Could not rename file %1 to %2</font><br>").arg(currentFileName, tmpfileTemplate));
    }

    if (folderRenamingInfo.currentPath != oldName.absolutePath()){
        if (isAutorenameFolders){
            QString tmpfolderTemplate = folderTemplate;

            tmpfolderTemplate.replace(tr("%Year"),   QString::number(Year));
            tmpfolderTemplate.replace(tr("%Album"),  Album);
            (Genre == "Soundtrack") ? tmpfolderTemplate.replace(tr("%Artist"), "Soundtrack") : tmpfolderTemplate.replace(tr("%Artist"), Artist);
            tmpfolderTemplate.replace(tr("%Genre"),  Genre);
            QString NewName = oldName.absolutePath().left(oldName.absolutePath().lastIndexOf("/") + 1) + tmpfolderTemplate;
            if (oldName.absolutePath() != NewName) folderRenamingInfo.renameFolderList.insert(oldName.absolutePath(), NewName);
        }

        if (isDownloadCovers){
            CoverDownloader->addDownloadJob(QString("%1 - %2").arg(Artist, Album), QString("%1 %2").arg(Album, Artist), oldName.absolutePath(), searchEngine);
        }

        folderRenamingInfo.currentPath = oldName.absolutePath();
    }

    readID3Tags();
}


// *********************************************************************************************
// Rename all MP3 folders
// *********************************************************************************************
void renameFiles::executeRenameFolders(){
    QDir dir;
    QHashIterator<QString, QString> i(folderRenamingInfo.renameFolderList);
    i.toFront();
    while (i.hasNext()) {
        i.next();

        // Try to prevent the biggest user mistakes
        // Disallow renaming of /home/USER and /home/USER/Desktop
        if (i.key() == QDir::homePath() || i.key() == QDir::homePath() + "Desktop"){
            emit signal_addToErrorlog(tr("<font color='red'>Skipped renaming of '%1'</font><br>").arg(i.key(),i.value()));
            continue;
        }

        bool val = dir.rename(i.key(), i.value());
        if (!val) emit signal_addToErrorlog(tr("<font color='red'>Could not rename folder '%1' to '%2'</font><br>").arg(i.key(),i.value()));
    }

    emit signal_allJobsFinished();
}


// *********************************************************************************************
// RegExp helper
// *********************************************************************************************
QString renameFiles::searchRegExp(QString searchValue, QString &Buffer){
    QRegExp rx(searchValue, Qt::CaseInsensitive, QRegExp::RegExp2);
    rx.setMinimal(true);

    rx.indexIn(Buffer);
    return rx.cap(1).trimmed();
}


// *********************************************************************************************
// Cancel all operations
// *********************************************************************************************
void renameFiles::cancelAllOperations(){
    isCancelAllJobs = true;
    Skipped = 0;
    Counter = 0;
    ID3Process->close();
    CoverDownloader->cancelAllDownloads();
    currentFileName.clear();
}


// *********************************************************************************************
// Update GUI-Infos via Signal/Slot (Coverdownload)
// *********************************************************************************************
void renameFiles::updateDownloadInfos(){
    emit signal_updateDownloadInfos(tr("Downloading Cover Artwork..."),         // QString Statustext,
                                    CoverDownloader->currentInterpretInfos(),   // QString Foldertext,
                                    "",                                         // QString Filetext,
                                    CoverDownloader->totalDownloadJobs() - CoverDownloader->completedDownloadJobs(),  // int ToDo,
                                    CoverDownloader->failedDownloadJobs(),      // int Error,
                                    CoverDownloader->skippedDownloadJobs(),     // int Skipped,
                                    0,                                          // int Gained,
                                    CoverDownloader->completedDownloadJobs(),   // int progressBarValue,
                                    CoverDownloader->totalDownloadJobs(),       // int progressBarMax,
                                    true);                                      // bool setDownloadIcon
}


// *********************************************************************************************
// Cover downloads finished, need we to rename folders?
// *********************************************************************************************
void renameFiles::allDownloadsFinished(){
    if (isAutorenameFolders) executeRenameFolders();
    Skipped = 0;
    Counter = 0;
    currentFileName.clear();
    emit signal_allJobsFinished();
}
