/***************************************************************************
                           tdefilereplacelib.cpp  -  File library
                                      -------------------
    begin                : lun mai  3 20:19:52 CEST 1999

    copyright            : (C) 1999 by Fran�ois Dupoux
                           (C) 2003 Andras Mantia <amantia@kde.org>
                           (C) 2004 Emiliano Gulmini <emi_barbarossa@yahoo.it>
    email                : dupoux@dupoux.com

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

//QT
#include <tqstringlist.h>
#include <tqwidget.h>
#include <tqlistview.h>
#include <tqfileinfo.h>

//KDE
#include <kdebug.h>
#include <tdemessagebox.h>
#include <tdelistview.h>
#include <kiconloader.h>

//needed for malloc/free
#include <stdlib.h>

// local
#include "tdefilereplacelib.h"

const double kilo = 1024.0;
const double mega = 1048576.0;//1024^2
const double giga = 1073741824.0;//1024^3
const double tera = 1099511627776.0;//1024^4

/**
 Format a path, from a path and a filename, or another sub-path (avoid double '/' risks)
 Parameters::.....* basePath: fist path (can be "/" if root, or "/usr/bin/" or "/usr/bin" for example)
 .................* fileName: second path (can be "/doc/html/", or "doc/html/" or "doc/html/index.html" for example)
 Return values:...* Full valid path (without double "/")
*/
TQString TDEFileReplaceLib::formatFullPath(const TQString& basePath, const TQString &fileName)
{
  TQString fullPath = basePath;
  TQString fname = fileName;

  if (fname.startsWith("/")) // skip beginning '/'
    fname = fname.remove(0,1);

  if (fullPath.endsWith("/"))
    fullPath.append(fname);
  else
    fullPath.append("/"+fname);

  return fullPath;
}

/**
 Add an extension to a filename, or a filepath
 Parameters::.....* fileName: filename or filepath (it can have already the extension)
 .................* extension: extension to add without "." (ex: "html", "kfr")
 Return values:...* Filename / Filepath with the extension
*/
TQString TDEFileReplaceLib::addExtension(const TQString& fileName, const TQString& extension)
{
  TQString fullExtension = ".";
  TQString fname = fileName;

  fullExtension.append(extension);

  // filename cannot contain ".ext" ==> Add it
  if(fname.length() <= fullExtension.length())
   fname.append(fullExtension);
  else // filename can contain ".ext"
  {
   if (fname.right(fullExtension.length()) != fullExtension)
    fname.append(fullExtension);
  }

  return fname;
}

TQString TDEFileReplaceLib::formatFileSize(double size)
{
  TQString stringSize;

  if(size < kilo)
    {
      const int asInt = (int) size;
      stringSize = i18n("1 byte", "%n bytes", asInt);
    }
  else
  if(size >= kilo && size < mega)
    {
      double d = size / kilo;
      stringSize = i18n("%1 KB").arg(TQString::number(d,'f',2));
    }
  else
  if(size >= mega && size < giga)
    {
      double d = size / mega;
      stringSize = i18n("%1 MB").arg(TQString::number(d,'f',2));
    }
  else
  if(size >= giga)
    {
      double d = size / giga;
      stringSize =  i18n("%1 GB").arg(TQString::number(d,'f',2));
    }
  return stringSize;
}

void TDEFileReplaceLib::convertOldToNewKFRFormat(const TQString& fileName, TDEListView* stringView)
{
 //this method convert old format in new XML-based format
 typedef struct
 {
   char pgm[13]; // Must be "TDEFileReplace" : like MZ for EXE files
   int stringNumber; // Number of strings in file
   char reserved[64]; // Reserved for future use
 } KFRHeader;

 KFRHeader head;

 FILE* f = fopen(fileName.ascii(),"rb");
 int err = fread(&head, sizeof(KFRHeader), 1, f);
 TQString pgm(head.pgm);

 if(!f || (err != 1) || (pgm != "TDEFileReplace"))
 {
   KMessageBox::error(0, i18n("<qt>Cannot open the file <b>%1</b> and load the string list. This file seems not to be a valid old kfr file or it is broken.</qt>").arg(fileName));
   return ;
 }

  stringView->clear();

  int oldTextSize,
      newTextSize,
      errors = 0,
      stringSize;
  TQStringList l;

  int i ;
  for (i=0; i < head.stringNumber; i++)
    {
      errors += (fread(&oldTextSize, sizeof(int), 1, f)) != 1;
      errors += (fread(&newTextSize, sizeof(int), 1, f)) != 1;
      if(errors > 0)
        KMessageBox::error(0, i18n("Cannot read data."));
      else
        {
          stringSize = ((oldTextSize > newTextSize) ? oldTextSize : newTextSize) + 2;
          char* oldString = (char*) malloc(stringSize+10),
              * newString = (char*) malloc(stringSize+10);
          memset(oldString, 0, stringSize);
          memset(newString,0, stringSize);
          if (oldString == 0 || newString == 0)
            KMessageBox::error(0, i18n("Out of memory."));
          else
            {
              if (fread(oldString, oldTextSize, 1, f) != 1)
                KMessageBox::error(0, i18n("Cannot read data."));
              else
                {
                  if (newTextSize > 0) // If there is a Replace text
                    {
                      if (fread(newString, newTextSize, 1, f) != 1)
                        KMessageBox::error(0, i18n("Cannot read data."));
                      else
                        {
                          TQListViewItem* lvi = new TQListViewItem(stringView);
                          lvi->setText(0,oldString);
                          lvi->setText(1,newString);

                          if(newString)
                            free(newString);
                          if(oldString)
                            free(oldString);
                        }
                    }
                }
            }
        }
    }
    fclose(f);
    return ;
 }

bool TDEFileReplaceLib::isAnAccessibleFile(const TQString& filePath, const TQString& fileName, RCOptions* info)
{
  TQString bkExt = info->m_backupExtension;
  if(fileName == ".." || fileName == "." || (!bkExt.isEmpty() && fileName.right(bkExt.length()) == bkExt))
    return false;

  TQFileInfo fi;
  if(filePath.isEmpty())
    fi.setFile(fileName);
  else
    fi.setFile(filePath+"/"+fileName);

  if(fi.isDir())
    return true;

   int minSize = info->m_minSize,
       maxSize = info->m_maxSize;
   TQString minDate = info->m_minDate,
           maxDate = info->m_maxDate,
           dateAccess = info->m_dateAccess;

  // Avoid files that not match access date requirements
  TQString last = "unknown";
  if(dateAccess == "Last Writing Access")
    last = fi.lastModified().toString(Qt::ISODate);
  if(dateAccess == "Last Reading Access")
    last = fi.lastRead().toString(Qt::ISODate);

  if(last != "unknown")
    {
      if(minDate != "unknown" && maxDate != "unknown")
        { //If out of range then exit
          if((minDate > last) || (maxDate < last))
            return false;
        }
      else
        {
          if(minDate != "unknown")
            { //If out of range then exit
              if(minDate > last)
                return false;
            }
          else
            {
              if(maxDate != "unknown")
              //If out of range then exit
              if(maxDate < last)
                return false;
            }
        }
    }
  // Avoid files that not match size requirements
  int size = fi.size();
  if(maxSize != FileSizeOption && minSize != FileSizeOption)
    if(size > (maxSize*1024) || size < (minSize*1024))
      return false;

  // Avoid files that not match ownership requirements
  if(info->m_ownerUserIsChecked)
    {
      TQString fileOwnerUser;
      if(info->m_ownerUserType == "Name")
        fileOwnerUser = fi.owner();
      else
        fileOwnerUser = TQString::number(fi.ownerId(),10);

      if(info->m_ownerUserBool == "Equals To")
        {
          if(info->m_ownerUserValue != fileOwnerUser)
            return false;
        }
      else
        {
          if(info->m_ownerUserValue == fileOwnerUser)
            return false;
        }
    }

  if(info->m_ownerGroupIsChecked)
    {
      TQString fileOwnerGroup;
      if(info->m_ownerGroupType == "Name")
        fileOwnerGroup = fi.group();
      else
        fileOwnerGroup = TQString::number(fi.groupId(),10);
      if(info->m_ownerGroupBool == "Equals To")
        {
          if(info->m_ownerGroupValue != fileOwnerGroup)
            return false;
        }
      else
        {
          if(info->m_ownerGroupValue == fileOwnerGroup)
            return false;
        }
    }

  //If we are here then all requirements have been verified
  return true;
}

void TDEFileReplaceLib::setIconForFileEntry(TQListViewItem* item, TQString path)
{
  TQFileInfo fi(path);
  TQString extension = fi.extension(),
          baseName = fi.baseName();

  KeyValueMap extensionMap;

  extensionMap["a"] = "application-octet-stream";
  extensionMap["am"] = "text-x-script";
  extensionMap["bz"] = "application-vnd.tde.overlay.zip";
  extensionMap["bz2"] = "application-vnd.tde.overlay.zip";
  extensionMap["c"] = "text-x-csrc";
  extensionMap["cc"] = "text-x-c++src";
  extensionMap["cpp"] = "text-x-c++src";
  extensionMap["eml"] = "message";
  extensionMap["exe"] = "application-x-mswinurl";
  extensionMap["gz"] = "application-vnd.tde.overlay.zip";
  extensionMap["h"] = "text-x-hsrc";
  extensionMap["htm"] = "text-html";
  extensionMap["html"] = "text-html";
  extensionMap["in"] = "text-x-script";
  extensionMap["java"] = "text-x-java";
  extensionMap["jpg"] = "image-x-generic";
  extensionMap["kfr"] = "text-html";
  extensionMap["kmdr"] = "application-x-designer";
  extensionMap["kwd"] = "x-office-document";
  extensionMap["log"] = "text-x-log";
  extensionMap["moc"] = "text-x-mocsrc";
  extensionMap["mp3"] = "audio-x-generic";
  extensionMap["o"] = "text-x-osrc";
  extensionMap["pdf"] = "application-pdf";
  extensionMap["php"] = "text-x-php";
  extensionMap["py"] = "text-x-python";
  extensionMap["pl"] = "text-x-perl";
  extensionMap["p"] = "text-x-psrc";
  extensionMap["ps"] = "application-postscript";
  extensionMap["png"] = "image-x-generic";
  extensionMap["sa"] = "application-octet-stream";
  extensionMap["sh"] = "text-x-script";
  extensionMap["so"] = "application-octet-stream";
  extensionMap["tar"] = "application-x-tar";
  extensionMap["tex"] = "text-x-tex";
  extensionMap["tgz"] = "application-x-tarz";
  extensionMap["txt"] = "text-plain";
  extensionMap["ui"] = "application-x-designer";
  extensionMap["uml"] = "umbrellofile";
  extensionMap["wav"] = "audio-x-generic";
  extensionMap["xml"] = "text-html";
  extensionMap["xpm"] = "image-x-generic";

  KeyValueMap::Iterator itExtensionMap;

  for(itExtensionMap = extensionMap.begin(); itExtensionMap != extensionMap.end(); ++itExtensionMap)
    {
      if(extension == itExtensionMap.key())
        {
          item->setPixmap(0,SmallIcon(itExtensionMap.data()));
          return;
        }
    }

  KeyValueMap baseNameMap;

  baseNameMap["configure"] = "text-x-script";
  baseNameMap["core"] = "application-x-core";
  baseNameMap["makefile"] = "text-x-makefile";
  baseNameMap["readme"] = "text-x-readme";
  baseNameMap["README"] = "text-x-readme";
  baseNameMap["Readme"] = "text-x-readme";
  baseNameMap["TODO"] = "text-plain";

  KeyValueMap::Iterator itBaseNameMap;

  for(itBaseNameMap = baseNameMap.begin(); itBaseNameMap != baseNameMap.end(); ++itBaseNameMap)
    {
      if(baseName == itBaseNameMap.key())
        {
          item->setPixmap(0,SmallIcon(itBaseNameMap.data()));
          return;
        }
    }
}