// telefonos.cpp - Definición de la clase CTelefonos
#include <iostream>
#include <string>
#include "persona.h"   // clase CPersona
#include "telefonos.h" // clase CTelefonos
#include "leerdatos.h"
using namespace std;

/////////////////////////////////////////////////////////////////
// Constructor
CTelefonos::CTelefonos()
{
  modo = 0;
}

CTelefonos::~CTelefonos()
{
  if (is_open()) close();
}

bool CTelefonos::Existe(string& nomf)
{
  // Deshabilitar las excepciones del tipo failure
  exceptions(ios::goodbit);
  // Intentar abrir el fichero para leer
  open(nomf.c_str(), ios::in);
  if (fail())
  {
    clear();
    return false;
  }
  close();
  return true;
}

CPersona CTelefonos::LeerReg(long nreg) throw(failure)
{
  // Habilitar las excepciones del tipo failure
  clear(); // desactivar los indicadores que haya activos
  exceptions(ios::failbit | ios::badbit);
  if (modo != 1)
    throw failure(string("Abrir el fichero para leer y escribir"));
  CPersona reg;
  seekp(0L, ios::end);
  long totalRegs = tellg() / reg.tamanyo();
  if (nreg < 1 || nreg > totalRegs)
    throw failure(string("Número de registro no válido"));
  // Leer el registro nreg (1, 2, ...)
  seekg((nreg-1)*reg.tamanyo(), ios::beg);
  read(reinterpret_cast<char *>(&reg), reg.tamanyo());
  return reg;
}

void CTelefonos::Nuevo(string& nomf) throw(failure)
{
  // Habilitar las excepciones del tipo failure
  clear(); // desactivar los indicadores que haya activos
  exceptions(ios::failbit | ios::badbit);
  // Crear un nuevo fichero
  if (nomf.empty())
    throw failure(string("Especificar un nombre para el fichero"));

  if (is_open()) close(); // cerrar el fichero si está abierto
  modo = 0;
  // Comprobar si el fichero existe
  if (Existe(nomf))
  {
    cout << "El fichero " << nomf << " existe. "
         << "¿Desea sobrescribirlo? (s/n): ";
    string resp("n");
    leerDato(resp);
    if (resp == "s")
    {
      // Eliminar todos sus registros
      open(nomf.c_str(), ios::out | ios::trunc);
      close();
    }
  }
  // Abrir el fichero para añadir registros
  open(nomf.c_str(), ios::out | ios::app | ios::binary);
  modo = 2; // añadir
}

void CTelefonos::Abrir(string& nomf) throw(failure)
{
  // Habilitar las excepciones del tipo failure
  clear(); // desactivar los indicadores que haya activos
  exceptions(ios::failbit | ios::badbit);
  // Abrir un fichero
  if (nomf.empty())
    throw failure(string("Especificar un nombre para el fichero"));

  if (is_open()) close(); // cerrar el fichero si está abierto
  modo = 0;
  // Opciones del menú
  static char *opciones[] = 
  { 
    "leer y escribir",
    "añadir",
  };
  int op, nOpciones = sizeof(opciones)/sizeof(char*);

  if ((op = menu(opciones, nOpciones)) == 1) // leer y escribir
    open(nomf.c_str(), ios::in | ios::out | ios::binary);
  else // añadir
    open(nomf.c_str(), ios::out | ios::app | ios::binary);
  modo = op;
}

void CTelefonos::Agregar() throw(failure)
{   
  // Habilitar las excepciones del tipo failure
  clear(); // desactivar los indicadores que haya activos
  exceptions(ios::failbit | ios::badbit);
  // Escribir registros en un fichero
  if (modo != 2)
    throw failure(string("Abrir el fichero para añadir"));

  CPersona reg;
  char nom[30];
  char dir[40];
  long tfno;
   
  cout << "\nIntroducir datos. Para finalizar, "
       << "responder \"fin\" a Nombre:.\n\n";
  while(true)
  {
    cout << "Nombre:    "; leerDato(nom);
    if (!strcmp(nom, "fin")) break;
    cout << "Dirección: "; leerDato(dir);
    cout << "Teléfono:  "; leerDato(tfno);
     
    reg = CPersona(nom, dir, tfno);
    write(reinterpret_cast<char *>(&reg), reg.tamanyo());
  }
}

long CTelefonos::Buscar(const char *str, long nreg)
{
  // Deshabilitar las excepciones del tipo failure
  exceptions(ios::goodbit);
  // Buscar un registro en el fichero y devolver su posición
  if (modo != 1)
  {
    cout << "Abrir el fichero para leer y escribir\n";
    return -1;
  }
  CPersona reg;
  
  char nom[30];
  // Buscar por el nombre
  if (str == 0) return -1;
  if (nreg <= 0) nreg = 1; // registro 1, 2, 3, ...
  // Situarse en el registro nreg
  seekg((nreg-1)*reg.tamanyo(), ios::beg);
  while (read(reinterpret_cast<char *>(&reg), reg.tamanyo()))
  {
    // Buscar por el nombre
    reg.obtenerNombre(nom);
    if (nom == 0) continue;
    // ¿str está contenida en nom?
    if (strstr(nom, str) != 0)
      return tellg()/reg.tamanyo(); // posición 1 a n del registro
  }
  clear(); // desactivar eofbit y failbit
  return -1;
}

void CTelefonos::Modificar() throw(failure)
{
  // Habilitar las excepciones del tipo failure
  clear(); // desactivar los indicadores que haya activos
  exceptions(ios::failbit | ios::badbit);
  // Buscar un registro en el fichero
  if (modo != 1)
    throw failure(string("Abrir el fichero para leer y escribir"));

  // Modificar un registro
  CPersona reg;
  // Calcular el número de registros
  seekp(0L, ios::end);
  long totalreg = tellp() / reg.tamanyo();

  // Solicitar el número de registro a modificar  
  long nreg, desp;
  do
  {
    cout << "\nNúmero de registro entre 1 y " << totalreg
         << " (0 para salir): ";
    leerDato(nreg);
    if (nreg > 0 && nreg <= totalreg)
    {
      desp = (nreg - 1) * reg.tamanyo();
      seekg(desp, ios::beg);  // posicionarse
      // Leer el registro
      read(reinterpret_cast<char*>(&reg), reg.tamanyo() );
      cout << endl << reg; // mostrar el registro leído

      // Modificar el dato referencia, precio, ambos o ninguno
      // Opciones del menú
      static char *opciones[] = 
      { 
        "nombre",
        "dirección",
        "teléfono",
        "salir y salvar los cambios",
        "salir sin salvar los cambios"
      };
      int op, nOpciones = sizeof(opciones)/sizeof(char*);
      char nom[30]; reg.obtenerNombre(nom);
      char dir[40]; reg.obtenerDireccion(dir);
      long tfno;   tfno = reg.obtenerTelefono();
      do
      {
        cout << "\nModificar el dato:";
        switch (op = menu(opciones, nOpciones))
        {
          case 1: // modificar el nombre
            cout << "Nombre:    "; leerDato(nom);
            break;
          case 2: // modificar la dirección
            cout << "Dirección: "; leerDato(dir);
            break;
          case 3: // modificar el teléfono
            cout << "Teléfono:  "; leerDato(tfno);
            break;
          case 4: // salir y guardar los cambios
            break;
          case 5: // salir sin guardar los cambios
            break;
        }
        reg = CPersona(nom, dir, tfno);
      }
      while (op != 4 && op != 5);
      if (op == 4)
      {
        seekp(-reg.tamanyo(), ios::cur);
        write(reinterpret_cast<char*>(&reg), reg.tamanyo());
      }
    }
    else if (nreg < 0)
      cout << "error: número de registro negativo\n";
  }
  while (nreg != 0);  
}
/////////////////////////////////////////////////////////////////
