//This file is part of AcetoneISO. Copyright 2006,2007,2008,2009 Fabrizio Di Marco and Marco Di Antonio (acetoneiso@gmail.com)
//Copyright 2010/2011 Marco Di Antonio

//    AcetoneISO 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.
//
//    AcetoneISO 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 AcetoneISO.  If not, see <http://www.gnu.org/licenses/>.


//read torrent list file in case there are torrents to download
void acetoneiso::readTorrentList() {
  QString saveTorrentToConfig = QDir::homePath() + "/.acetoneiso/torrentList.cfg";
  QFile fileSave(saveTorrentToConfig);
  if (!fileSave.exists() ) {
   return; 
  }
  fileSave.open(QIODevice::ReadOnly | QIODevice::Text); 
  fileSave.seek(0);
  while (!fileSave.atEnd()) {
   QString realread = fileSave.readLine() ;
   realread = realread.remove("\n")  ;
   if (realread.isEmpty() ) {
    continue; 
   }
   QStringList list = realread.split("?;?");
   if (list.count() < 2) {
    continue; 
   }
   QString filepath = list[0];
   QString name = list[1];
   QFile check(filepath);
   if (!check.exists()) {
    continue; 
   }

   runTorrent(name,filepath);
  // qDebug() << "File is: "<< filepath;
  // qDebug() << "Name is: " << name << "\n";
  }
  
  fileSave.close();
}


//item selection changed in qtreewidget
void acetoneiso:: itemTorrentChanged() {
  QList<QTreeWidgetItem *> listaItems = torrentWidget->selectedItems();
  if (listaItems.count() < 1) {
   pauseTorrentButton->setEnabled(false);
   removeTorrentButton->setEnabled(false);
   indexTorrentIs = -1;
   return;
  }
  indexTorrentIs = torrentWidget->indexOfTopLevelItem(listaItems[0]);
  pauseTorrentButton->setEnabled(true);
  removeTorrentButton->setEnabled(true);
}


//main tab index changed
void acetoneiso::mainTabChanged(int index) {
  if (index != 2) {
    dockWidget1->show();
    return;
  }
  if (!dockWidget1->isFloating() ) { 
    dockWidget1->hide(); //hide if in torrent tab and its not floating
  }
}

//opens torrent from http
void acetoneiso::openUrlTorrent() {
  QFile checkAriaExist("/usr/bin/aria2c");
  if (!checkAriaExist.exists() ) {
    QMessageBox::critical(this, "AcetoneISO::Aria2c not found!",tr("Unable to find /usr/bin/aria2c file.\nPlease install aria2 package."));
    return;
  }


  bool ok;
  QString text = QInputDialog::getText(this, tr("AcetoneISO::Insert Torrent URL"),
                                          tr("Insert Torrent URL:"), QLineEdit::Normal,
                                          "", &ok);
  if (!ok && text.isEmpty()) { 
    return;
  }
  
  qDebug() << text;
  
}


//opens torrent from local file
void acetoneiso::openTorrent() {  

  QFile checkAriaExist("/usr/bin/aria2c");
  if (!checkAriaExist.exists() ) {
    QMessageBox::critical(this, "AcetoneISO::Aria2c not found!",tr("Unable to find /usr/bin/aria2c file.\nPlease install aria2 package."));
    return;
  }
  
  QDir Home = QDir::home();// entro nella home dell'utente
  QString torrentOpenF;
  torrentOpenF = QFileDialog::getOpenFileName(this,tr("Open Torrent"), Home.path() , tr("Torrent (*.torrent)"));
  if ( torrentOpenF.isNull() )  {
    return;   
  }
  
  handleTorrentName(torrentOpenF);
  
}

//gets torrent real name to put in widget
void acetoneiso::handleTorrentName(QString torrent) {
  global_torrent_file = torrent;
  QDir bin("/usr/bin");
  QDir::setCurrent( bin.absolutePath() );

  aria2cTorrentName = new QProcess();
  aria2cTorrentName->setReadChannel(QProcess::StandardOutput);
  aria2cTorrentName->setProcessChannelMode(QProcess::MergedChannels);	
  connect(aria2cTorrentName, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(ariaGotName(int, QProcess::ExitStatus)));
  //connection to update the display
  connect(aria2cTorrentName, SIGNAL(readyReadStandardOutput()), SLOT(AriaName() ));
  aria2cTorrentName->start("aria2c --show-files \"" + torrent + "\"" );  
   
}
//realtime reads process that gets torrent name
void acetoneiso::AriaName() {
  aria2RealNameOutput_temp = aria2cTorrentName->readAllStandardOutput(); 
  //questo evita che prende un output vuoto
  if (aria2RealNameOutput_temp.size() < 2 ) {
    return;
  }
  aria2RealNameOutput = aria2RealNameOutput_temp;
}
//aria finished getting the real torrent name
void acetoneiso::ariaGotName(int, QProcess::ExitStatus) {
  int valore_uscita = aria2cTorrentName->exitCode();
  if(valore_uscita == 1) {
    QMessageBox::critical(this, "AcetoneISO::Error!",tr("Error retrieving torrent file name."));
    return;    
  }

  QByteArray string = aria2RealNameOutput ;
  QTextStream read(string);
  read.seek(0);
  RealTorrentName = "";
  while (true) {
    if (read.atEnd() ) {
      QMessageBox::critical(this, "AcetoneISO::Error!",tr("Error retrieving torrent file name."));
      return; 
    }
    QString name = read.readLine();
    if (!name.contains("name: ", Qt::CaseInsensitive) ) {
      continue;
    }
    RealTorrentName = (name.split(": ") )[1];
    break;
  }
  
  //save torrent to save cfg file
  saveTorrentListCFG();
  
  //qDebug() << RealTorrentName;
  runTorrent(RealTorrentName,global_torrent_file);
}

//saves added torrent to save list, used when reopening acetoneiso
void acetoneiso::saveTorrentListCFG() {
  //append torrent in save file, needed when restarting acetoneiso
  QString saveTorrentToConfig = QDir::homePath() + "/.acetoneiso/torrentList.cfg";
  QFile fileSave(saveTorrentToConfig);
  fileSave.open(QIODevice::Append | QIODevice::Text);
  QTextStream out(&fileSave);
  //append torrent file full path + realtorrent name  + the directory where to download it
  out << ("\n" + global_torrent_file + "?;?" + RealTorrentName);
  fileSave.close();  
}


//starts the final aria2c process
void acetoneiso::runTorrent(QString torrent, QString file) {

  //fill first item in widget
  item_file = new QTreeWidgetItem(torrentWidget);
  item_file->setText(0, torrent);
  item_file->setTextAlignment(0, 0x0001); 
  QString infinite = QString::fromUtf8("\xe2\x88\x9e");
  item_file->setText(4,infinite); 
  icon_downloading = new QIcon(":/images/downloading.png");
  icon_completed = new QIcon(":/images/dialog-ok.png");
  item_file->setIcon( 0,*icon_downloading ); 
 
  //store item object in array
  item_list.append(item_file);  
  
  
  //connect(erase, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(printOutErase(int, QProcess::ExitStatus)));
  QDir bin("/usr/bin");
  QDir::setCurrent( bin.absolutePath() );

  aria2c = new QProcess();
  
  aria2c->setReadChannel(QProcess::StandardOutput);
  aria2c->setProcessChannelMode(QProcess::MergedChannels);	
  //connection to update the display
  connect(aria2c, SIGNAL(readyReadStandardOutput()), SLOT(AriaDisplay() ));
  aria2c->start("aria2c --allow-overwrite=true --log-level=info --check-certificate=false --summary-interval=0 -d /home/bulletxt \"" + file + "\"");  
  
  //store process object in array
  process_list.append(aria2c);
  
  //global hash table QProcess key, value contains  torrent file full path followed by its real internal torrent name
  processId_torrentName[aria2c] = file + "?;?" + torrent;
  //qDebug() << "QHash:"  << processId_torrentName[aria2c];
  
} 
 

//gets called each time aria2c process has an output
void acetoneiso::AriaDisplay() {
  
  //prento l'ID oggetto che ha chiamato questa funzione, in questo caso un QProcess
  QProcess* processID = qobject_cast<QProcess*>(sender());
  
  int countLista = process_list.count();
  int conta = 0;
  while (conta < countLista) {
    if (process_list[conta] != processID) {
	conta = conta + 1;
	continue;
    }
    break;  
  }
  
  
  aria2_output = process_list[conta]->readAllStandardOutput(); 
  qDebug() << aria2_output;
  
  //questo evita che prende un output vuoto
  if (aria2_output.size() < 2 ) {
    return;
  }
  QString notifica = aria2_output;
  if (notifica.contains("notice",Qt::CaseInsensitive) ) {
    return; 
  }
  
  //divide complete string separating parts based on a space filter
  QString remove_spaces_from_complete_string;
  remove_spaces_from_complete_string = aria2_output;
  QStringList list;
  list = remove_spaces_from_complete_string.split(QRegExp("\\s+"));

  


  //check for bad url and immediate aria2c error->quit
  QString string_error_url = aria2_output;
  
  //check if seeding
  QString seedingIS = aria2_output;
  if (seedingIS.contains("seeding", Qt::CaseInsensitive) ) {
    item_list[conta]->setText(1, tr("Completed"));  
    item_list[conta]->setText(4, "");
    item_list[conta]->setText(3, "");
    item_list[conta]->setText(5, "");
    item_list[conta]->setText(7, "");
    item_list[conta]->setText(6, "");
    item_list[conta]->setIcon( 0,* icon_completed );
    process_list[conta]->disconnect(SIGNAL(readyReadStandardOutput()));
    process_list[conta]->terminate();
    process_list[conta]->kill();
    
    //remove torrent from config list
    QFile cleanFile(QDir::homePath() + "/.acetoneiso/torrentList.cfg");
    cleanFile.open(QIODevice::ReadOnly | QIODevice::Text); 
    QByteArray read_for_removal = cleanFile.readAll();
    cleanFile.close();
    cleanFile.remove();
    QString lineToRemove = processId_torrentName.value(processID)  ;
    QString cleanedTorrent = read_for_removal;
    cleanedTorrent = cleanedTorrent.remove( "\n" + lineToRemove);
    //qDebug() << "CLEANED FILE: " << cleanedTorrent;
    cleanFile.open(QIODevice::ReadWrite); 
    QTextStream outClean(&cleanFile);
    outClean <<  cleanedTorrent;
    outClean.flush();
    cleanFile.close();
    
    QString torrent_process_getName = (processId_torrentName.value(processID) ).split("?;?")[1]  ;
    torrent_process_getName.prepend("Torrent finished downloading!\n");
    QMessageBox::information(this, "AcetoneISO::Torrent", torrent_process_getName );
    return;
  }
  
  
  
  
  bool error_url;
  error_url = string_error_url.contains("ERROR", Qt::CaseInsensitive); 
  //if true error on url
  if (error_url) {
    QString remove_aria_specific_stuff = "If there are any errors, then see the log file. See '-l' option in help/man page for details.";
    string_error_url = string_error_url.remove( remove_aria_specific_stuff, Qt::CaseInsensitive);
    remove_aria_specific_stuff = "aria2 will resume download if the transfer is restarted.";
    string_error_url = string_error_url.remove( remove_aria_specific_stuff, Qt::CaseInsensitive);
    //QMessageBox::critical(this, tr("AcetoneISO::Error"),string_error_url);
    item_list[conta]->setText(7, string_error_url);
   // process_list[conta]->disconnect(SIGNAL(finished(int, QProcess::ExitStatus)));
   // process_list[conta]->disconnect(SIGNAL(readyReadStandardOutput()));
    return;
  }
  
  


  //check if is doing file alloc
  if (list.count() > 4) {
    if (list[5].contains("filealloc", Qt::CaseInsensitive) ) {
    item_list[conta]->setText(1, "0%");
    item_list[conta]->setText(2, tr("Calculating..."));
    item_list[conta]->setText(3, "0KiBs");
    QString infinite = QString::fromUtf8("\xe2\x88\x9e");
    infinite = infinite.append(tr(" (File Alloc, Please Wait...)"));
    item_list[conta]->setText(4,infinite);
    return;
    }
  }
	
	
  //speed
  QString speed;
  speed = list[4];
  QStringList speed_list;
  speed_list = speed.split(QRegExp(":"));
  speed = speed_list[1].remove("]");
  item_list[conta]->setText(3, speed);
	
  //progress
  QString progress;
  progress = list[1];
  QStringList progress_list;
  progress_list = progress.split("(");
  progress = progress_list[1].remove(QChar(')'), Qt::CaseInsensitive);
  item_list[conta]->setText(1, progress);

  //size
  QString size;
  size = list[1];
  QString no_percentage;
  no_percentage = progress_list[0]; //contiene tutto size: senza (n%)
  QStringList size_list;
  size_list = no_percentage.split(QRegExp(":"));
  item_list[conta]->setText(2, size_list[1]);

  //ETA
  QString containsETA = aria2_output;
  if (containsETA.contains("ETA",Qt::CaseInsensitive ) ) {
    QStringList splitEta = containsETA.split("ETA",QString::SkipEmptyParts) ;
    containsETA = (splitEta[splitEta.count() - 1]).split(":")[1].split("]")[0]    ;
    item_list[conta]->setText(4, containsETA );
  }
  else {
    item_list[conta]->setText(4, "" );
  }
 
 
//SEED list[3]
  QString seed;
  seed = ( (list[3]).split(":") )[1]  ;
  item_list[conta]->setText(5, seed);
//CN list[2]
  QString leech;
  leech = ( (list[2]).split(":") )[1]  ;
  item_list[conta]->setText(6,leech );  

}
 

//quanto lutente chiude acetone, chiudere tutti i process torrent
void acetoneiso:: closeAllTorrents() {
  int countLista = process_list.count();
  int conta = 0;
  while (conta < countLista) {
    process_list[conta]->terminate();
    process_list[conta]->kill();
    conta = conta + 1;
  } 
  
}
 

 
 
 
 
 
 
 
 