/*
 *
 *  Visual Voicemail Daemon
 *
 *  Copyright (C) 2022, Chris Talbot <chris@talbothome.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <glib.h>
#include <glib/gprintf.h>

#include "vvmutil.h"

static void
test_sms (gconstpointer data)
{
  struct sms_control_message *sms_msg = NULL;

  const char vzw_usa_sync_sms_0[] = "//VZWVVM:SYNC:ev=NM;id=132;c=1;t=v;s=00000000000;dt=23/06/2021 22:08 -0500;l=10;dev_t=5";
  // This is an unprovisioned status SMS
  const char vzw_usa_status_sms_0[] = "//VZWVVM:STATUS:rc=3;st=U;vmg_url=https://vmg.vzw.com/VMGIMS/VMServices";
  // This is a provisioned status SMS
  const char vzw_usa_status_sms_1[] = "//VZWVVM:STATUS:st=R;rc=0;srv=blt2lv.imsvm.com;ipt=143;u=00000000000@vzwazc.com;pw=removed;lang=1,2,3,4,5,6,7,8;g_len=60;vs_len=10;pw_len=4-7;dev_t=5;vmg_url=https://vmg.vzw.com/VMGIMS/VMServices";
  //This is an example SYNC Message from OTMP VVM Specification:
  const char otmp_sync_sms_0[] = "//VVM:SYNC:ev=NM;id=3446456;c=1;t=v;s=01234567898;dt=02/08/200812:53 +0200;l=30";
  //This is an example STATUS Message from OTMP VVM Specification:
  const char otmp_status_sms_0[] = "//VVM:STATUS:st=N;rc=0;srv=1:10.115.67.251;tui=123;dn=999;ipt=143;spt=25;u=78236487@wirelesscarrier.com;pw=32u4yguetrr34;lang=eng|fre;g_len=25;vs_len=15;pw_len=4-6;smtp_u=super_user@wirelesscarrier.com;smtp_pw=48769463wer;pm=Y;gm=N;vtc=D;vt=1";

  const char t_mobile_usa_sync_sms_0[] = "//VVM:SYNC:ev=NM;id=328;c=1;t=v;s=11235556754;dt=28/07/2022 17:45 -0700;l=9";
  const char t_mobile_usa_status_sms_0[] = "//VVM:STATUS:st=R;rc=0;srv=vvm.mstore.msg.t-mobile.com;ipt=148;u=12125551234;pw=rh84hf77dh;lang=1|2|3|4;g_len=180;vs_len=10;pw_len=4-9";


  //This is a sync SMS
  const char att_usa_sync_sms_0[] = "vvm.mobile.att.net:5400?f=0&v=1010&m=1235550000&p=&S=I&s=5433&i=143/993&t=4:1235550000:A:CMSGROUP0241238:ms06:client:31413";

  //From AWESim, they are blocked
  const char awesim_status_sms_0[] = "GET?AD=\"vvm.mobile.att.net:5400?v=1010&S=U&s=5433&m=1235550000\"";

  //This is an ready status SMS
  const char att_usa_status_sms_0[] = "vvm.mobile.att.net:5400?f=0&v=1010&m=1235550000&p=WFRRXlpTVVVfWTAwMDAw&P=WFRRXlpTVVVfWTAwMDAw&S=I&s=5433&i=143/993&t=4:1235550000:A:CMSGROUP024121413";

  //This is an unprovisioned status SMS
  //pw looks to be a first password? And the last 7 digits of "name"
  const char att_usa_status_sms_1[] = "STATE?state=NewAccount;server=vvm.mobile.att.net;port=143;name=4:1235550000:A:CMSGROUP0241238:ms06:NAT:31413;pw=5550000";

  //FreeMobile
  //This is a provisioned status SMS
  const char freemobile_fr_status_sms_0[] = "STATE?state=NewAccount;name=1234567;server=vvm.proxad.net;port=993;pw=PASSWORD";
  //This is a provisioned status SMS
  const char freemobile_fr_status_sms_1[] = "STATE?state=Active;server=vvm.proxad.net;port=993;pw=PASSWORD;name=1234567";
  //This is an unprovisioned status SMS
  const char freemobile_fr_status_sms_2[] = "STATE?state=NotAvailable";
  //This is a sync SMS
  const char freemobile_fr_sync_sms_0[] = "MBOXUPDATE?m=1";

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (vzw_usa_sync_sms_0, "//VZWVVM", "vvm3") == SMS_MESSAGE_SYNC);
  vvm_util_parse_sync_sms_message (vzw_usa_sync_sms_0, sms_msg, "vvm3");
  //ev
  g_assert (sms_msg->sync_status_reason == SYNC_SMS_NEW_MESSAGE);
  //id
  g_assert (g_strcmp0 (sms_msg->uid, "132") == 0);
  //c
  g_assert (g_strcmp0 (sms_msg->new_mailbox_messages, "1") == 0);
  //t
  g_assert (sms_msg->mailbox_message_type == MAILBOX_MESSAGE_VOICE);
  //s
  g_assert (g_strcmp0 (sms_msg->message_sender, "00000000000") == 0);
  //dt
  g_assert (g_strcmp0 (sms_msg->message_date, "23/06/2021 22:08 -0500") == 0);
  //l
  g_assert (g_strcmp0 (sms_msg->message_length, "10") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (vzw_usa_status_sms_0, "//VZWVVM", "vvm3") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (vzw_usa_status_sms_0, sms_msg, "vvm3");
  //Don't parse rc
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_UNKNOWN);
  //vmg_url
  g_assert (g_strcmp0 (sms_msg->activate_url, "https://vmg.vzw.com/VMGIMS/VMServices") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (vzw_usa_status_sms_1, "//VZWVVM", "vvm3") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (vzw_usa_status_sms_1, sms_msg, "vvm3");
  //Don't parse rc
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_READY);
  //srv
  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "blt2lv.imsvm.com") == 0);
  //ipt
  g_assert (g_strcmp0 (sms_msg->mailbox_port, "143") == 0);
  //u
  g_assert (g_strcmp0 (sms_msg->mailbox_username, "00000000000@vzwazc.com") == 0);
  //pw
  g_assert (g_strcmp0 (sms_msg->mailbox_password, "removed") == 0);
  //lang
  g_assert (g_strcmp0 (sms_msg->language, "1,2,3,4,5,6,7,8") == 0);
  //g_len
  g_assert (g_strcmp0 (sms_msg->greeting_length, "60") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->voice_signature_length, "10") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->TUI_password_length, "4-7") == 0);
  //vmg_url
  g_assert (g_strcmp0 (sms_msg->activate_url, "https://vmg.vzw.com/VMGIMS/VMServices") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (otmp_sync_sms_0, "//VVM", "otmp") == SMS_MESSAGE_SYNC);
  vvm_util_parse_sync_sms_message (otmp_sync_sms_0, sms_msg, "otmp");
  //ev
  g_assert (sms_msg->sync_status_reason == SYNC_SMS_NEW_MESSAGE);
  //id
  g_assert (g_strcmp0 (sms_msg->uid, "3446456") == 0);
  //c
  g_assert (g_strcmp0 (sms_msg->new_mailbox_messages, "1") == 0);
  //t
  g_assert (sms_msg->mailbox_message_type == MAILBOX_MESSAGE_VOICE);
  //s
  g_assert (g_strcmp0 (sms_msg->message_sender, "01234567898") == 0);
  //dt
  g_assert (g_strcmp0 (sms_msg->message_date, "02/08/200812:53 +0200") == 0);
  //l
  g_assert (g_strcmp0 (sms_msg->message_length, "30") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (otmp_status_sms_0, "//VVM", "otmp") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (otmp_status_sms_0, sms_msg, "otmp");
  //Don't parse rc
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_NEW);
  //srv
  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "1:10.115.67.251") == 0);
  //ipt
  g_assert (g_strcmp0 (sms_msg->mailbox_port, "143") == 0);
  //u
  g_assert (g_strcmp0 (sms_msg->mailbox_username, "78236487@wirelesscarrier.com") == 0);
  //pw
  g_assert (g_strcmp0 (sms_msg->mailbox_password, "32u4yguetrr34") == 0);
  //lang
  g_assert (g_strcmp0 (sms_msg->language, "eng|fre") == 0);
  //g_len
  g_assert (g_strcmp0 (sms_msg->greeting_length, "25") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->voice_signature_length, "15") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->TUI_password_length, "4-6") == 0);


  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (t_mobile_usa_sync_sms_0, "//VVM", "cvvm") == SMS_MESSAGE_SYNC);
  vvm_util_parse_sync_sms_message (t_mobile_usa_sync_sms_0, sms_msg, "cvvm");
  //ev
  g_assert (sms_msg->sync_status_reason == SYNC_SMS_NEW_MESSAGE);
  //id
  g_assert (g_strcmp0 (sms_msg->uid, "328") == 0);
  //c
  g_assert (g_strcmp0 (sms_msg->new_mailbox_messages, "1") == 0);
  //t
  g_assert (sms_msg->mailbox_message_type == MAILBOX_MESSAGE_VOICE);
  //s
  g_assert (g_strcmp0 (sms_msg->message_sender, "11235556754") == 0);
  //dt
  g_assert (g_strcmp0 (sms_msg->message_date, "28/07/2022 17:45 -0700") == 0);
  //l
  g_assert (g_strcmp0 (sms_msg->message_length, "9") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (t_mobile_usa_status_sms_0, "//VVM", "cvvm") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (t_mobile_usa_status_sms_0, sms_msg, "cvvm");
  //Don't parse rc
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_READY);
  //srv
  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "vvm.mstore.msg.t-mobile.com") == 0);
  //ipt
  g_assert (g_strcmp0 (sms_msg->mailbox_port, "148") == 0);
  //u
  g_assert (g_strcmp0 (sms_msg->mailbox_username, "12125551234") == 0);
  //pw
  g_assert (g_strcmp0 (sms_msg->mailbox_password, "rh84hf77dh") == 0);
  //lang
  g_assert (g_strcmp0 (sms_msg->language, "1|2|3|4") == 0);
  //g_len
  g_assert (g_strcmp0 (sms_msg->greeting_length, "180") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->voice_signature_length, "10") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->TUI_password_length, "4-9") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }

  // AT&T has pretty much identical STATUS and SYNC messages, and the SYNC
  // Messages aren't helpful, just process all as STATUS SMS
  g_assert (vvm_util_parse_sms_message_type (att_usa_sync_sms_0, "1235550000", "AT&TUSAProprietary") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (att_usa_sync_sms_0, sms_msg, "AT&TUSAProprietary");
  //Don't parse rc
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_READY);
  //srv
  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "vvm.mobile.att.net") == 0);
  //ipt
  g_assert (g_strcmp0 (sms_msg->mailbox_port, "143") == 0);
  //u
  g_assert (g_strcmp0 (sms_msg->mailbox_username, "1235550000") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->TUI_password_length, "7-15") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (att_usa_status_sms_0, "1235550000", "AT&TUSAProprietary") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (att_usa_status_sms_0, sms_msg, "AT&TUSAProprietary");
  //Don't parse rc
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_READY);
  //srv
  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "vvm.mobile.att.net") == 0);
  //ipt
  g_assert (g_strcmp0 (sms_msg->mailbox_port, "143") == 0);
  //u
  g_assert (g_strcmp0 (sms_msg->mailbox_username, "1235550000") == 0);
  //pw
  g_assert (g_strcmp0 (sms_msg->mailbox_password, "000000000000000") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->TUI_password_length, "7-15") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }
  g_assert (vvm_util_parse_sms_message_type (awesim_status_sms_0, "1235550000", "AT&TUSAProprietary") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (awesim_status_sms_0, sms_msg, "AT&TUSAProprietary");
  //Don't parse rc
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_UNKNOWN);
  //srv
  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "vvm.mobile.att.net") == 0);
  //u
  g_assert (g_strcmp0 (sms_msg->mailbox_username, "1235550000") == 0);
  //vs_len
  g_assert (g_strcmp0 (sms_msg->TUI_password_length, "7-15") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }

  g_assert (vvm_util_parse_sms_message_type (att_usa_status_sms_1, "1235550000", "AT&TUSAProprietary") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (att_usa_status_sms_1, sms_msg, "AT&TUSAProprietary");

  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_NEW);

  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "vvm.mobile.att.net") == 0);

  g_assert (g_strcmp0 (sms_msg->mailbox_port, "143") == 0);

  g_assert (g_strcmp0 (sms_msg->mailbox_username, "1235550000") == 0);

  g_assert (g_strcmp0 (sms_msg->mailbox_password, "5550000") == 0);

  g_assert (g_strcmp0 (sms_msg->TUI_password_length, "7-15") == 0);

  vvm_util_delete_status_message (sms_msg);

  //Freemobile message
  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }

  g_assert (vvm_util_parse_sms_message_type (freemobile_fr_status_sms_0, "//VVM", "FreeMobileProprietary") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (freemobile_fr_status_sms_0, sms_msg, "FreeMobileProprietary");
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_NEW);
  //server
  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "vvm.proxad.net") == 0);
  //port
  g_assert (g_strcmp0 (sms_msg->mailbox_port, "993") == 0);
  //name
  g_assert (g_strcmp0 (sms_msg->mailbox_username, "1234567") == 0);
  //password
  g_assert (g_strcmp0 (sms_msg->mailbox_password, "PASSWORD") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }

  g_assert (vvm_util_parse_sms_message_type (freemobile_fr_status_sms_1, "//VVM", "FreeMobileProprietary") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (freemobile_fr_status_sms_1, sms_msg, "FreeMobileProprietary");
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_READY);
  //server
  g_assert (g_strcmp0 (sms_msg->mailbox_hostname, "vvm.proxad.net") == 0);
  //port
  g_assert (g_strcmp0 (sms_msg->mailbox_port, "993") == 0);
  //name
  g_assert (g_strcmp0 (sms_msg->mailbox_username, "1234567") == 0);
  //password
  g_assert (g_strcmp0 (sms_msg->mailbox_password, "PASSWORD") == 0);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }

  g_assert (vvm_util_parse_sms_message_type (freemobile_fr_status_sms_2, "//VVM", "FreeMobileProprietary") == SMS_MESSAGE_STATUS);
  vvm_util_parse_status_sms_message (freemobile_fr_status_sms_2, sms_msg, "FreeMobileProprietary");
  //st
  g_assert (sms_msg->provision_status == VVM_PROVISION_STATUS_BLOCKED);

  vvm_util_delete_status_message (sms_msg);

  sms_msg = g_try_new0 (struct sms_control_message, 1);
  if (sms_msg == NULL)
    {
      g_critical ("Could not allocate space for SMS SYNC Message!");
      g_assert (FALSE);
    }

  g_assert (vvm_util_parse_sms_message_type (freemobile_fr_sync_sms_0, "//VVM", "FreeMobileProprietary") == SMS_MESSAGE_SYNC);
  vvm_util_parse_sync_sms_message (freemobile_fr_status_sms_0, sms_msg, "FreeMobileProprietary");
  //Mailbox Update
  g_assert (sms_msg->sync_status_reason == SYNC_SMS_MAILBOX_UPDATE);

  vvm_util_delete_status_message (sms_msg);
}

int
main (int    argc,
      char **argv)
{
  g_test_init (&argc, &argv, NULL);

  g_test_add_data_func ("/vvmutil/SMS Test",
                        NULL, test_sms);


  return g_test_run ();
}
