/***************************************************************************
                          world.cpp  -  description
                             -------------------
    begin                : mar dic 17 2002
    copyright            : (C) 2002 by Jaime Robles
    email                : jaime@kde.org
 ***************************************************************************/

/******************************************************************************
 *                                                                            *
 *   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 <klocale.h>
//#include <kdebug.h>
//#include <ostream.h>
#include "world.h"
 
World::World(){
    prefix = "NULL"; // It is just a fake prefix to start with
     int cqzone = 0; 
     int ituzone = 0;
     QString finalPrefix;
     

  created = false;
  number = 0;

  QStringList lines;
  World::klogDir = QDir::homeDirPath()+"/.klog/";  // We create the ~/.klog for the logs
  QFile file( klogDir+"cty.dat" );
  if (!file.exists()){ // If the cty.dat file is not in the KLOG home, maybe it is in the current directory
      klogDir=QDir::currentDirPath();   // Maybe it is in the current Path??
      file.setName( klogDir+"/cty.dat" );
  /*}else if (!file.exists()){
      klogDir=QDir::homeDirPath();  // Maybe it is in the user's home path???
      file.setName( klogDir+"/cty.dat" );      
      cout << "homeDirPath: " << QDir::homeDirPath() << endl;
      */
}
// I have no idea where cty.dat is!!!
  
      
      
      
  if ( file.open( IO_ReadOnly ) ) {
    QTextStream stream( &file );
    QString line;
    while ( !stream.eof() ) {
      number++;
      // Read a Line and get all data
      QString data = stream.readLine();
      // We split the line
      QStringList fields = QStringList::split(SEPARATOR1, data );
      cqzone = fields[1].toInt();
      ituzone = fields[2].toInt();
    entity.setNumb(number);
    entity.setEntity( fields[0].latin1() );
    entity.setPfx(fields[7].latin1());
    entity.setCqz(cqzone);
    entity.setLon(fields[5].toDouble());
    entity.setLat( fields[4].toDouble());
    entity.setContinent( fields[3].latin1());
    entity.setItuz(ituzone);
    entity.setTimeZone( fields[6].toInt());
    World::nmap[number] = entity;
      //I create another data stream to process all prefixes
      // and then split the line
      QString datab = stream.readLine();
      datab.remove(0,4);  //removing the spaces at the begining of the lines
      QStringList prefs = QStringList::split(SEPARATOR2, datab );
      //While the line does not have a ";"
      while( !(datab.contains(';') ) ){
        ij = (datab.contains(','));
        n = 0;
        while (n < ij){
     cqzone = fields[1].toInt();
     ituzone = fields[2].toInt();
     finalPrefix = prefs[n];
     
     // Here I have the prefix but also the (zone)[zone] when special zone is added 
     // HERE IS NECESARY TO CHECK IF THIS IS A SPECIAL PREFIX IN A DIFFERENT ZONE (CQ OR ITU)
        if (prefs[n].contains('(')>0 ){ // The prefix contains special CQzone
     cqzone = (prefs[n].section('(',1)).section(')',0,0).toInt();
        }

        if (prefs[n].contains('[')>0 ){ // The prefix contains special CQzone
         ituzone = (prefs[n].section('[',1)).section(']',0,0).toInt();
        }
 
 if (prefs[n].contains('[') ){
          finalPrefix = prefs[n].left(prefs[n].find('['));
        }
        if (prefs[n].contains('(') ){
          finalPrefix = prefs[n].left(prefs[n].find('('));      
        }
     
     
     World::cqMap[finalPrefix] = cqzone;
            World::ituMap[finalPrefix] = ituzone;    
            World::map[finalPrefix] = entity;
          //entity.addPrefix(prefs[n].latin1());
          n++;
        }//
        datab = stream.readLine();
        datab.remove(0,4);  //removing the spaces at the begining of the lines
        prefs = QStringList::split(SEPARATOR2, datab );
      }// Now we will process when there is ";"
      ij = (datab.contains(','));
      n = 0;
      while (n <= ij){  // Maybe it is only <, not <=
        if (prefs[n].contains(';')){
          j = prefs[n].length() - 1;
          prefs[n].truncate(j);
//          entity.addPrefix(prefs[n].latin1());
        }else{
        }
 finalPrefix = prefs[n];
 
 // Is a prefix with a Zone?
 
 
 // HERE IS NECESARY TO CHECK IF THIS IS A SPECIAL PREFIX IN A DIFFERENT ZONE (CQ OR ITU)
        if (prefs[n].contains('(')>0 ){ // The prefix contains special CQzone
     cqzone = (prefs[n].section('(',1)).section(')',0,0).toInt();
        }

        if (prefs[n].contains('[')>0 ){ // The prefix contains special CQzone
         ituzone = (prefs[n].section('[',1)).section(']',0,0).toInt();
        }
 if (prefs[n].contains('[') ){
          finalPrefix = prefs[n].left(prefs[n].find('['));
        }
        if (prefs[n].contains('(') ){
          finalPrefix = prefs[n].left(prefs[n].find('('));      
        }

 World::cqMap[finalPrefix] = cqzone;
 World::ituMap[finalPrefix] = ituzone;    
        World::map[finalPrefix] = entity;

        n++;
      }

    }
  created = true;
  file.close();


  }else{ //There is no cty.dat
    //ADD A QMESSAGEBOX

  }


  
//  wnumber = 0;
}

World::~World(){
}


// We create the world reading from a file "cty.dat"
void World::create(){

}

QString World::getPrefix() const{
    return prefix;   
}


// We obtain the Entity from a call
// It receives a string, get the prefix and send it to
//   bool Entity::findPrefix(const QString tprx)
// for each prefix till find the country in the list.
// Once we have find the country we return its number or
// "0" if we have not found it.

int World::findEntity(const QString string){
    
    
  // The first task is to isolate the prefix

  prefixa = string;
  prefixab = string;
  prefix = "NULL";
  qrz = prefixa;      // For last checks
  qrz2 = qrz;
  i = 0;

      
  if(( (prefixa.contains('/')) || (prefixa.contains('\\')) )){
      
      i = giveEnt(prefixa); // Checking full "special prefixes" like "4U/OH2BBF" first
      if (i!=0){
//   prefix = prefixa;
   return i;
      }
      
    if (prefixa.contains('/')){
      ij = prefixa.find('/');
      if ( (abs)(ij) < (abs)((prefixa.length())- ij)  ) { //Like in F/EA4TV
        prefixab = prefixa.left(ij);
        qrz2 = prefixab;        
      }else{// Like in EA4TV/F
         if (!((prefixa.upper()).endsWith("/P"))
            && !((prefixa.upper()).endsWith("/M"))
            && (!(prefixa.upper()).endsWith("/QRP"))
            && (!(prefixa.upper()).endsWith("/0"))
            && (!(prefixa.upper()).endsWith("/1"))
            && (!(prefixa.upper()).endsWith("/2"))
            && (!(prefixa.upper()).endsWith("/3"))
            && (!(prefixa.upper()).endsWith("/4"))
            && (!(prefixa.upper()).endsWith("/5"))
            && (!(prefixa.upper()).endsWith("/6"))
            && (!(prefixa.upper()).endsWith("/7"))
            && (!(prefixa.upper()).endsWith("/8"))
            && (!(prefixa.upper()).endsWith("/9")))
        //if( (prefixa.right( (prefixa.length())-ij-1) != "P") && (prefixa.right( (prefixa.length())-ij-1) != "QRP"))
        {
            prefixab = prefixa.right(prefixa.length()-(ij+1));
        }else{  // It is a EA4TV/P or EA4TV/QRP       
          //prefixab =  prefixa.left( (prefixa.length())-ij-1);
          prefixab =  prefixa.left(ij);           
/*          if (prefixab == "3XDQC"){ // HACK: This is a rare case of an specific non-usual call. (3XDQC/P)
       prefixa = "3X";
            }
*/
        }
        qrz2 = prefixab;
      }
    }else{
      ij = prefixa.find("\\");
      if ( (abs)(ij) < (abs)(prefixa.length()-ij ) ) { //Like in F\EA4TV
        prefixab = prefixa.right(prefixa.length() - ij);
        qrz2 = prefixab;        
      }else{// Like in F\EA4TV
        prefixab =  prefixa.left(ij-1);
        qrz2 = prefixab;        
      }      
    }
  }
  prefixa = prefixab;

  i = giveEnt(prefixa); // Checking full calls like "4U1ITU" first
  if (i!=0){
//      prefix = prefixa;
      return i;
  }
  //////////  Begin the "Normal" check
  if ((prefixa.at(1)).isDigit()){ // The second character is a number as in F5XX
    prefixa.truncate(2);
    i = giveEnt(prefixa);
    if ((i == 0) && ((prefixab.at(2)).isDigit()) ){ // Then is a P40A call...
      prefixa = prefixab;
      prefixa.truncate(1);
      i = giveEnt(prefixa);
    }else if ((i == 0) && (!(prefixab.at(2)).isDigit()) ){ // Then is a F call...
      prefixa = prefixab;
      prefixa.truncate(1);
      i = giveEnt(prefixa);
    }
//    prefix = prefixa;
    
  }else if ((prefixa.at(2)).isDigit()){ // The third character is a number as in EA4T
    prefixa.truncate(3); // We will look for EA6, ZS8... prefixes
    i = giveEnt(prefixa);
    if (i == 0){
 prefixa = prefixab;
 prefixa.truncate(2);
 i = giveEnt(prefixa);
    }else{ // If it is not 0, we have detected the Entity. No reason to keep running this.
 return i;
    }
    
    if (i == 0){ // Prefixes as VP2M
      prefixa=prefixab;
      prefixa.truncate(4);
      i = giveEnt(prefixa);
    }else{ // If it is not 0, we have detected the Entity. No reason to keep running this.
        return i;
    }
  }else if ((prefixa.at(3)).isDigit()){ // The forth character is a number as in 3DA0SV
    prefixa.truncate(4); // We will look for 3DA0 or 3XY7C
    i = giveEnt(prefixa);
    if (i == 0){
      prefixa = prefixab;
      prefixa.truncate(3);
      i = giveEnt(prefixa);
   }
  }/*else if(){  // Here i am planning to look for 3XDQC calls.
  //EAABW
  }
*/
  if (i == 0){ // I want to look for calls like RA3AA or NA3A
  // The real prefix is just one letter but the next char is NOT a number
  // so the first condition is not satistied.
    prefixa = prefixab;
    if ((prefixa.at(2)).isDigit()){
      prefixa.truncate(1);
      i = giveEnt(prefixa);
    }
  }else{ // If it is not 0, we have detected the Entity. No reason to keep running this.
       return i;
  }
  if (i == 0){
    i = giveEnt(qrz);
  }else{ // If it is not 0, we have detected the Entity. No reason to keep running this.
 return i;
    }

  if (i == 0){ // We have to test for calls as 5U when reading from a log file
    i = giveEnt(qrz2);
  }else{
     return i;
  }

  if (i == 0){  // We have to test for calls as KL7 when
                  // reading from a log file as we truncate -1 to look for KL
    qrz2.truncate(qrz2.length() -1);
    i = giveEnt(qrz2);
  }else{
     return i;
  }


  // We have to check for calls as 3XY1L when reading from a file
  // but just if we have not find another Entity
  if (i == 0){      
    if ( ((prefixa.at(3)).isDigit()) && !(prefixa.at(2).isDigit())){ // The forth character is a number as in 3DA0SV
      prefixa.truncate(2); // We will look for 3X
      i = giveEnt(prefixa);
      if (i == 0){
        prefixa.truncate(1); // Maybe it is a F like station
 i = giveEnt(prefixa);   
      }     
  }else if((prefixa.at(0)).isDigit()){ // HACK: Looking for 3XDQC stile calls
      prefixa.truncate(2);
      i = giveEnt(prefixa);
  }
  }  
  
  return i; // "i" is the Entity number
}



Entity World::getEntByNumb(int num){
  i = num;
/***********************************************************
* We receive the number and we try to get the Entity returning *
* a pointer to it                                          *
************************************************************
*/
// Maybe the way to proceed is to check without running all the list!  
  
  itN = nmap.begin();
  itN = nmap.find(i);
  if (itN != nmap.end()){
      return (itN.data());
  }else{
      itN = nmap.begin();
  }
  return (itN.data());  
      
/*  
 // found = false;
   for ( it = map.begin(); it != map.end(); ++it ) {
    if ( (it.data().getNumb()) == i){
        return (it.data());
    }
   }
    it = map.end();
    return (it.data());
*/  
}


int World::giveEnt(const QString tqrz){ 
  qrz = tqrz;
  it = map.begin();
  it = map.find(qrz);
  if (map.find(qrz) != map.end()){
      prefix = qrz;
      return it.data().getNumb();
  }
  else
    return 0;
}

bool World::isSpecial(const QString &tpfx){  // This functions returns true if Entity has special zones
                                        // per prefixes i.e. BY, UA, ...
  qrz = tpfx;
  it = map.begin();
  it = map.find(qrz);
  if (map.find(qrz) != map.end()){
      return it.data().getNumb();
  }
  else
    return 0;    
}    

int World::getItuz(){  
    if (prefix=="NULL") // We are calling this function just after start KLog
 return 0;
    
//  qrz = prefix;
  itITU = ituMap.begin();
  itITU = ituMap.find(prefix);
  if (ituMap.find(prefix) != ituMap.end()){
      return itITU.data();
  }
  else
    return 0;        
}

  //EntityZMap cqMap, ituMap;
  //EntityNMap::Iterator itCQ, itITU;  
  
int World::getCqz(){  
 // qrz = tpfx;
    if (prefix=="NULL") // We are calling this function just after start KLog
 return 0;
    
  itCQ = cqMap.begin();
  itCQ = cqMap.find(prefix);
  if (cqMap.find(prefix) != cqMap.end()){
      return itCQ.data();
  }
  else
    return 0;        
}



int World::howManyEntities(){
  it = map.end();
  return it.data().getNumb();
}

bool World::isWorldCreated(){
    return created;}
