/***************************************************************************
 *   copyright           : (C) 2004 by Hendrik Sattler                     *
 *   mail                : post@hendrik-sattler.de                         *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "scmxx.h"
#include "atcommand.h"
#include "helper.h"
#include "gtincl.h"

#include <stdio.h>
#include <string.h>
#include <strings.h>

char* lock_get_longname (const char* shortname) {
  if (strcasecmp(shortname,"PS") == 0) {
    return _("phone locked to SIM (device code)");
  } else if (strcasecmp(shortname,"SC") == 0) {
    return _("SIM card (PIN)");
  } else if (strcasecmp(shortname,"P2") == 0) {
    return "PIN2";
  } else if (strcasecmp(shortname,"FD") == 0) {
    return _("FDN lock");
  } else if (strcasecmp(shortname,"AO") == 0) {
    return _("bar all outgoing calls");
  } else if (strcasecmp(shortname,"OI") == 0) {
    return _("bar outgoing international calls");
  } else if (strcasecmp(shortname,"OX") == 0) {
    return _("bar outgoing international calls except to home country");
  } else if (strcasecmp(shortname,"AI") == 0) {
    return _("bar all incoming calls");
  } else if (strcasecmp(shortname,"IR") == 0) {
    return _("bar incoming calls when roaming outside the home country");
  } else if (strcasecmp(shortname,"AB") == 0) {
    return _("all barring services");
  } else if (strcasecmp(shortname,"AG") == 0) {
    return _("all outgoing barring services");
  } else if (strcasecmp(shortname,"AC") == 0) {
    return _("all incoming barring services");
  } else if (strcasecmp(shortname,"PN") == 0) {
    return _("network personalization");
  } else if (strcasecmp(shortname,"PC") == 0) {
    return _("corporate personalization");
  } else if (strcasecmp(shortname,"PU") == 0) {
    return _("network subset personalization");
  } else if (strcasecmp(shortname,"PP") == 0) {
    return _("service provider personalization");
  } else if (strcasecmp(shortname,"PF") == 0) {
    return _("phone locked to very first inserted SIM");
  } else if (strcasecmp(shortname,"CS") == 0) {
    return _("keyboard");
  } else {
    return NULL;
  }  
}

int lock_set_pass (const char* lock,
		   const char* oldpin,
		   const char* newpin)
{
  char* ausgabe = NULL;
  char* temp = NULL;
  enum return_code status;
  char* command = NULL;

  if (lock == NULL ||
      (str_len(oldpin) == 0 && str_len(newpin) == 0))
    return 0;

  if (str_len(oldpin) == 0) oldpin = NULL;
  if (str_len(newpin) == 0) newpin = NULL;

  command = at_sie_password(lock,oldpin,newpin);
  ausgabe = at_read_line();
  status = at_line_type(ausgabe,command,&temp);
  mem_realloc(ausgabe,0);
  if (status&AT_RET_ERROR) {
    print_warning("%s\n",_("Be beware of phone internal passwort counters that are normally set to 3 failures!"));
    print_warning("%s\n",_("The current failure count cannot be read!"));
    errexit("%s\n",_("Setting new password FAILED!"));
  } else {
    return 1;
  }
}

int lock_get_status (const char* lock) {
  char* ausgabe = NULL;
  char* temp = NULL;
  enum return_code status;
  int retval = -1;
  int value = 0;
  unsigned short class = 0;
  char* command = NULL;

  if (lock == NULL) return 0;

  command = at_sie_lock(lock,2,NULL,0);
  do {
    ausgabe = at_read_line();
    status = at_line_type(ausgabe,command,&temp);
    if (status == AT_RET_ANSWER) {
      retval = atoi(temp);
      temp = strchr(temp,',');
      if (temp != NULL) {
	class = atoi(temp+1);	
	value += retval*class;
      }
    }    
    mem_realloc(ausgabe,0);
  } while (status == AT_RET_ANSWER);
  if (value != 0) return value;
  else return retval;
}

int lock_enable (const char* lock, const char* password) {
  int retval = -1;
  char* ausgabe = NULL;
  enum return_code status;
  char* command = NULL;

  if (lock == NULL) return 0;

  command = at_sie_lock(lock,1,password,0);
  ausgabe = at_read_line();
  status = at_line_type(ausgabe,command,NULL);
  if (status == AT_RET_OK) {
    retval = lock_get_status(lock);
  }
  mem_realloc(ausgabe,0);
  return retval;
}

int lock_disable (const char* lock, const char* password) {
  int retval = -1;
  char* ausgabe = NULL;
  enum return_code status;
  char* command = NULL;

  if (lock == NULL) return 0;

  command = at_sie_lock(lock,0,password,0);
  ausgabe = at_read_line();
  status = at_line_type(ausgabe,command,NULL);
  if (status == AT_RET_OK) {
    retval = lock_get_status(lock);
  }
  mem_realloc(ausgabe,0);
  return retval;
}

void lock_toggle (const char* lock, const char* password) {
  int status = lock_get_status(lock);

  if (lock == NULL) return;

  if  (status == -1 ||
       (status == 0 && lock_enable(lock,password) <= 0) ||
       (status == 1 && lock_disable(lock,password) != 0)) {
    errexit("%s\n",_("Lock status change failed."));
  } else {
    print_verbose(0,_("Lock %s successfully %s.\n"),lock,
	     (status)? _("disabled") : _("enabled"));
	     
  }
}

void lock_print_list (FILE* fd, unsigned int full) {
  char* ausgabe = NULL;
  char* temp = NULL;
  enum return_code status;
  char** list = NULL;
  unsigned int l;
  unsigned int i;
  int code;

  const unsigned int columns = 3;
  struct table_column {
    char* name;
    unsigned int width;
  } table[columns];
  char* entry[columns];

  char* command = NULL;
  char* vendor = at_get_vendor();

  if (fd == NULL) {
    mem_realloc(vendor,0);
    return;
  }

  if (strcasecmp(vendor,"SIEMENS") == 0) {
    command = AT_SIE_LOCK;
  } else {
    command = AT_GEN_LOCK;
  }
  mem_realloc(vendor,0);
  at_command_send(command,AT_READ_SUFFIX);
  ausgabe = at_read_line();
  status = at_line_type(ausgabe,command,&temp);
  if (status == AT_RET_ANSWER) {
    mem_realloc(at_read_line(),0);
    memmove(ausgabe,temp,strlen(temp)+1);
    list = at_parse_stringlist(ausgabe);
    fprintf(fd,"%s: ",_("Locks"));
    if (!full) {
      for (i = 0; list[i] != 0; ++i) {
	if (i != 0) fprintf(fd,", ");
	fprintf(fd,"%s",list[i]);
      }
    } else {
      table[0].name = _("lock");
      table[1].name = _("status");
      table[2].name = _("description");

      fprintf(fd,"\n");
      for (i = 0; i < columns; ++i) {
	table[i].width = strlen(table[i].name);
	entry[i] = mem_alloc((table[i].width+1)*sizeof(char),1);
	fprintf(fd,"%-*s  ",table[i].width,table[i].name);
      }
      fprintf(fd,"\n");
      for (i = 0; i < columns; ++i) {
	memset(entry[i],'-',table[i].width);
	fprintf(fd,"%s  ",entry[i]);
      }
      fprintf(fd,"\n");
      mem_realloc(entry[0],0);
      mem_realloc(entry[columns-1],0);

      for (l = 0; list[l] != NULL; ++l) {
	code = lock_get_status(list[l]);
	if (code == -1) {
	  print_verbose(0,"%s %s(%s): %s\n",
			_("Lock"), list[l],
			lock_get_longname(list[l]),
			_("getting lock status failed."));
	} else {
	  entry[0] = list[l];

	  sprintf(entry[1],"%s",(code)? _("on") : _("off"));
	  entry[columns-1] = lock_get_longname(list[l]);
	  for (i = 0; i < columns-1; ++i) {
	    fprintf(fd,"%-*s  ",table[i].width,entry[i]);
	  }
	  if (entry[columns-1] != NULL) {
	    fprintf(fd,"%s",entry[columns-1]);	
	  }
	  fprintf(fd,"\n");
	}	
      }
    }
    fprintf(fd,"\n");
    mem_realloc(*list,0);
    mem_realloc(list,0);
  }
}
