/*
  View / change mail routes
  (c) 1999 by Radek Burget OK2JBG
*/

#include <vector.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>

#define OUT_FILE "/var/ax25/mail_routes"

#define HOME_COUNT 5

//-----------------------------------------------------------------------
// class addr
//-----------------------------------------------------------------------
class route_addr
{
  public:
    char call[10];
    char route[36];
    int count;
    int pcount;
    time_t ttime;

    route_addr();
    route_addr &operator = (const route_addr &);
};

route_addr &route_addr::operator = (const route_addr &src)
{
  strcpy(call, src.call);
  strcpy(route, src.route);
  count = src.count;
  pcount = src.pcount;
  ttime = src.ttime;
  return *this;
}

route_addr::route_addr()
{
  strcpy(call, "");
  strcpy(route, "");
  count = 0;
  pcount = 0;
  ttime = 0;
}


vector <route_addr> routes;


    
//-----------------------------------------------------------------------

//read the database
bool read_database()
{
  FILE *f = fopen(OUT_FILE, "r");
  if (f == NULL) return false;
  while (!feof(f))
  {
    char line[256];
    char call[256];
    char route[256];
    int count, pcount;
    time_t ttime;
    route_addr newaddr;

    strcpy(line, "");
    fgets(line, 255, f);
    int n = sscanf(line, "%s %s %i %i %li", call, route, &count, &pcount, &ttime);
    if (n == 5)
    {
      strncpy(newaddr.call, call, 10);
      strncpy(newaddr.route, route, 35);
      newaddr.count = count;
      newaddr.ttime = ttime;
      newaddr.pcount = pcount;
      routes.push_back(newaddr);
    }
  }
  return true;
}

void force_home(char *call, char *route)
{
  vector <route_addr>::iterator it;

  if (routes.empty())
  {
    route_addr newaddr;
    newaddr.count = 1;
    newaddr.ttime = -1;
    strcpy(newaddr.call, call);
    strcpy(newaddr.route, route);
    routes.push_back(newaddr);
  }
  else
  {
    //unmark previous home BBS
    for (it = routes.begin(); it < routes.end(); it++)
      if (strcmp(it->call, call) == 0 && it->ttime == -1)
      {
        it->ttime = 0; //record will be completely updated
        it->count = 0;
        it->pcount = 0;
      }

    it = routes.begin();
    while (it < routes.end() &&
           (strcmp(it->call, call) < 0 ||
            (strcmp(it->call, call) == 0 && strcmp(it->route, route) < 0)))
              it++;

    if (it < routes.end() && strcmp(call, it->call) == 0 && strcmp(route, it->route) == 0)
    {
      it->ttime = -1;
    }
    else
    {
      route_addr newaddr;
      strcpy(newaddr.call, call);
      strcpy(newaddr.route, route);
      newaddr.count = 1;
      newaddr.ttime = -1;
      if (it < routes.end()) routes.insert(it, newaddr);
      else routes.push_back(newaddr);
    }
  }
}



int main(int argc, char **argv)
{
  if (argc < 2 || argc > 3)
  {
    printf("View: home_bbs <callsign>\n");
    printf("Change: home_bbs <callsign> <bbs_address>\n");
    return 1;
  }

  //read old data
  if (!read_database())
    fprintf(stderr, "Warning: Cannot open routing database %s - creating new\n", OUT_FILE);

  for (char *p = argv[1]; *p; p++) *p = toupper(*p);
  char *call = argv[1];

  if (argc == 2) //view
  {
    vector <route_addr> cands;
    vector <route_addr>::iterator it, home;
    bool found = false;
    //select candidates
    for (it = routes.begin(); it < routes.end(); it++)
      if (strcmp(call, it->call) == 0) cands.push_back(*it);
    if (cands.empty())
    {
      printf("%s's home BBS is unknown\n", call);
      return 0;
    }
    //find the forced home (time = -1)
    for (it = cands.begin(); it < cands.end(); it++)
      if (it->ttime == -1)
      {
        home = it;
        found = true;
      }
    //find the bbs with PCOUNT > HOME_COUNT
    if (!found)
      for (it = cands.begin(); it < cands.end(); it++)
        if (it->pcount > HOME_COUNT)
        {
          home = it;
          found = true;
        }
    //if not found return the most used BBS
    if (!found)
    {
      home = cands.begin();
      for (it = cands.begin(); it < cands.end(); it++)
        if (it->count > home->count) home = it;
    }
    printf("Most probable address of %s is\n", call);
    printf("  %s@%s\n", call, home->route);
    if (cands.size() > 1)
    {
      printf("Other possibilities are:\n");
      for (it = cands.begin(); it < cands.end(); it++)
        if (it != home) printf("  %s@%s  (used %ix)\n", call, it->route, it->count);
    }
  }
  else //edit
  {
    for (char *p = argv[2]; *p; p++) *p = toupper(*p);
    force_home(call, argv[2]);

    //write the database
    FILE *f = fopen(OUT_FILE, "w");
    if (f == NULL)
    {
      fprintf(stderr, "Cannot write to %s\n", OUT_FILE);
      return 1;
    }
  
    vector <route_addr>::iterator it;
    for (it = routes.begin(); it < routes.end(); it++)
      fprintf(f, "%s\t%s\t%i\t%i\t%li\n", it->call, it->route, it->count, it->pcount, it->ttime);
  
    fclose(f);
  }
  
  return 0;
}

