/*
    KSocrat
    Version 3.1.2, 28 April 2003    
    (C) 2000-2003 Zavolzhsky Alexandr <zavolzhsky@mail.ru>

    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., 675 Mass Ave, Cambridge, MA 02139, USA.  
*/

#include <qaccel.h>
#include <qfile.h>
#include <qtextcodec.h>
#include <kapp.h>
#include <kconfig.h>
#include <kstddirs.h>
#include <kfiledialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kaboutapplication.h>
#include <kglobalaccel.h>
#include <ctype.h>
#include "dockwidget.h"
#include "ksocrat.h"

DockWidget *dw;

KSocrat::KSocrat(const char *name) : KMainWindow(0L,name){
    initDialog();
    readConfig(true);
    sconfigure = new SConfigure();

    dw = new DockWidget(this);
    
    bGrepFree = true;

    connect(edWord,SIGNAL(returnPressed()),SLOT(translate()));
    connect(btClear,SIGNAL(clicked()),this,SLOT(clearall()));
    connect(btTranslate,SIGNAL(clicked()),this,SLOT(translate()));
    connect(btSave,SIGNAL(clicked()),this,SLOT(save()));	
    connect(btAbout,SIGNAL(clicked()),this,SLOT(about()));		
    connect(btConfigure,SIGNAL(clicked()),this,SLOT(configure()));
    connect(btExit,SIGNAL(clicked()),this,SLOT(quit()));
    connect(cbSentTrans,SIGNAL(clicked()),this,SLOT(setKeepTransState()));
    connect(kapp,SIGNAL(shutDown()),this,SLOT(appClosing()));
    connect(btHide,SIGNAL(clicked()),this,SLOT(hide()));

    connect(&prGrep,SIGNAL(processExited(KProcess *)),this,SLOT(done()));
    connect(&prGrep,SIGNAL(receivedStdout(KProcess *,char *,int)),this,SLOT(gotResult(KProcess *,char *,int)));
    connect(&prGrep,SIGNAL(receivedStderr(KProcess *,char *,int)),this,SLOT(gotError(KProcess *,char *,int)));

    QAccel *skey = new QAccel(this);
    skey->connectItem(skey->insertItem(ALT+Key_T),this,SLOT(translate()));
    skey->connectItem(skey->insertItem(ALT+Key_S),this,SLOT(save()));	
    skey->connectItem(skey->insertItem(ALT+Key_A),this,SLOT(about()));	
    skey->connectItem(skey->insertItem(ALT+Key_P),this,SLOT(configure()));	
    skey->connectItem(skey->insertItem(ALT+Key_X),this,SLOT(quit()));
    skey->connectItem(skey->insertItem(ALT+Key_C),this,SLOT(clearall()));
    skey->connectItem(skey->insertItem(ALT+Key_H),this,SLOT(hide()));

    KGlobalAccel *gkey = new KGlobalAccel(this);
    gkey->insert("show-hide",i18n("Show/Hide"),i18n("Show/Hide"),CTRL+ALT+Key_S,
              CTRL+ALT+Key_S,this,SLOT(show_hide()),false,true);
    gkey->updateConnections();
}

KSocrat::~KSocrat(){                                  
}

void KSocrat::translate(){
    sWord = edWord->currentText();
    sWord = sWord.stripWhiteSpace();
    sWord = sWord.lower();
    
    if (!sWord.isEmpty() && checkDicPath()) {
        
        if (cbAutoLanguage->isChecked()) {
          const char *c = sWord.data();
          if(isalpha(c[0])) {
            rbEnglish->setChecked(true);
            }
          else {
            rbRussian->setChecked(true);
            }
        }
              
        btTranslate->setEnabled(false);
        if (rbEnglish->isChecked()) {
            sDic=sEnRuDic;
        }
        else {
            sDic=sRuEnDic;
        }

        if (cbSentTrans->isChecked()) {
          meResult->insertLine(i18n("TRANSLATING: ") + sWord);
          meResult->insertLine("====================");
          QStringList sl;
          sl = QStringList::split(" ",sWord,false);

          for ( QStringList::Iterator it = sl.begin(); it != sl.end(); ++it ) {
            QString sWord(*it);
            QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
            QCString csWord = codec->fromUnicode(sWord);

            prGrep.clearArguments();
            prGrep << "grep" << "\"^"+ csWord + "\\ --" + "\"" << sDic;

            bGrepFree = false;
            if (!prGrep.start(KProcess::NotifyOnExit,KProcess::Stdout)) {
              KMessageBox::error(this,i18n("Cannot execute grep utility!"),i18n("Error"));
              break;
            }

            while (!bGrepFree) {

              if (!prGrep.isRunning()) {
                if (prGrep.exitStatus() != 0) {
                  break;
                }
              }

              kapp->processEvents();
              sleep(1);
            }

          }
        }
        
        else {
          QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
          QCString csWord = codec->fromUnicode(sWord);
          
          prGrep.clearArguments();
          prGrep << "grep" << "\"^"+ csWord +"\"" << sDic;

          if (!cbKeepTrans->isChecked()) {
            meResult->clear();
          }

          bGrepFree = false;
          if (!prGrep.start(KProcess::NotifyOnExit,KProcess::Stdout)) {
              KMessageBox::error(this,i18n("Cannot execute grep utility!"),i18n("Error"));
          }
        }
        
    }
}

void KSocrat::save(){
    QString sName = KFileDialog::getSaveFileName("/");
    if (!sName.isEmpty()) {
        if (sName.right(1)=="/") {
            KMessageBox::error(this,i18n("You need to specify name of the file."),i18n("Warning"));
        }
        else {
            QFile fData(sName);
            int iSize = (meResult->text()).length();
            if (fData.open(IO_WriteOnly)) {
                QString sText = meResult->text();
                QTextCodec* codec = QTextCodec::codecForName("KOI8-R");
                fData.writeBlock(codec->fromUnicode(sText),iSize);
                fData.close();
            }
            else {
               KMessageBox::error(this,i18n("Cannot save translation to file!"),i18n("Error"));
            }
        }
    }
}

void KSocrat::done(){
    btTranslate->setEnabled(true);
}

void KSocrat::gotResult(KProcess *,char *msg, int len){
    QString sMsg;
    QTextCodec* codec = QTextCodec::codecForName("KOI8-R");
    sMsg = codec->toUnicode(msg,len);
    
    meResult->insertLine(sMsg);
    meResult->insertLine("--------------------------------");
    bGrepFree = true;
}

void KSocrat::gotError(KProcess *,char *msg,int len){
    QString sMsg;
    QTextCodec* codec = QTextCodec::codecForName("KOI8-R");
    sMsg = codec->toUnicode(msg,len);
    KMessageBox::information(this,sMsg,i18n("Warning"));
    bGrepFree = true;
}

void KSocrat::about(){
    KAboutApplication *ap = new KAboutApplication(this,"ksocrat-about");
    ap->exec();
}

void KSocrat::configure(){
    saveHistory();
    sconfigure->exec();
    readConfig(false);
}

void KSocrat::quit(){
    saveHistory();
    kapp->quit();
}

void KSocrat::readConfig(bool bSetFont){
    config = kapp->config();
    
    config->setGroup("Dictionary");    
    KStandardDirs *dataDir = new KStandardDirs();
    sEnRuDic = dataDir->findResource("data","ksocrat/enru.dic");
    if (sEnRuDic.isNull()) {
      sEnRuDic = config->readEntry("EnRuPath","");
    }
    sRuEnDic = dataDir->findResource("data","ksocrat/ruen.dic");
    if (sRuEnDic.isNull()) {
      sRuEnDic = config->readEntry("RuEnPath","");
    }
    
    if (bSetFont){
        config->setGroup("General");
        kapp->setFont(config->readFontEntry("Font"),true);
    }

    config->setGroup("General");
    QStringList slHistory;
    slHistory = config->readListEntry("History");
    edWord->clear();
    edWord->insertStringList(slHistory,1);
}

bool KSocrat::checkDicPath(){
    QFile fEnRuDic(sEnRuDic);
    QFile fRuEnDic(sRuEnDic);
    if (!fEnRuDic.exists()) {
        KMessageBox::error(this,i18n("Cannot find English/Russian dictionary!"),i18n("Error"));
        return false;
    }
    if (!fRuEnDic.exists()) {
        KMessageBox::error(this,i18n("Cannot find Russian/English dictionary!"),i18n("Error"));
        return false;
    }
    return true;
}

void KSocrat::clearall() {
    edWord->clearEdit();
    meResult->clear();
    edWord->setFocus();
}

void KSocrat::setKeepTransState() {
  if (cbSentTrans->isChecked()) {
    cbKeepTrans->setChecked(true);
    cbKeepTrans->setEnabled(false);
  }
  else {
    cbKeepTrans->setChecked(false);
    cbKeepTrans->setEnabled(true);    
  }
}

void KSocrat::appClosing() {
  saveHistory();
}

void KSocrat::saveHistory() {
    config = kapp->config();
    config->setGroup("General");

    QStringList slHistory;
    for(int i = 0; i<= (edWord->count()) - 1; i++) {
       slHistory.append(edWord->text(i));
    }
    config->writeEntry("History",slHistory);
    config->sync();
}

void KSocrat::resizeEvent (QResizeEvent * ) {
  meResult->setGeometry(5,115,this->width() - 10,this->height() - 160);
  btSave->setGeometry(5,this->height() - 32,60,24);
  btConfigure->setGeometry(70,this->height() - 32,60,24);
  btAbout->setGeometry(135,this->height() - 32,60,24);
  btHide->setGeometry(200,this->height() - 32,50,24);
  btExit->setGeometry(255,this->height() - 32,50,24);
}

void KSocrat::show_hide(){
  if (this->isVisible()) {
    this->hide();
  }
  else {
    this->show();
  }
}
