<?php
require_once('../componenthelper.inc.php');
require_once(__DIR__ . '/Twilio/autoload.php');
use Twilio\Rest\Client;

pre_init();
init_session();
check_authentication();

grab_request_vars();
check_prereqs();

route_request();

/**
* Route AJAX request from twilio.inc.php
*/
function route_request()
{
    // grab request values
    $mode = grab_request_var('mode');
    $mobile_number = grab_request_var('mobile_number');
    $user_id = grab_request_var('user_id');
    $user_twilio_key = grab_request_var('user_twilio_key');
    $country_code = grab_request_var('country_selected');
    $mobile_country_code = grab_request_var('mobile_country_code');

    // ajax request variables from configuration page
    $sid = grab_request_var('sid');
    $token = grab_request_var('token');
    $twilio_country_code = grab_request_var('twilio_country_code');
    $twilio_phone_number = grab_request_var('twilio_phone_number');
    $twilio_test_country_code = grab_request_var('twilio_test_country_code');
    $test_twilio_phone = grab_request_var('test_twilio_phone');

    // route with mode
    switch ($mode) {

    case 'send_twilio_user_phone_vkey':
        send_twilio_user_phone_vkey($user_id, $mobile_country_code);
        break;

    case 'verify_vkey':
        verify_twilio_phone_vkey($user_id, $user_twilio_key);
        break;

    case 'update_user_vtag':
        get_user_twilio_phone_vtag($user_id);
        break;            

    case 'countdown':
        twilio_countdown($user_id);
        break;

    case 'resend':
        send_twilio_user_phone_vkey($user_id, $mobile_country_code);
        break;

    case 'twilio_country_code':
        save_country_code($user_id, $country_code, 'twilio_country_code');
        break;    
    
    case 'get_twilio_country_code':
        echo get_country_code($user_id, 'twilio_country_code');
        break;

    case 'twilio_test_country_code':
        save_country_code($user_id, $country_code, 'twilio_test_country_code');
        break;

    case 'get_twilio_test_country_code':
        echo get_country_code($user_id, 'twilio_test_country_code');
        break;

    case 'mobile_country_code':
        save_country_code($user_id, $country_code, 'mobile_country_code');
        break;

    case 'get_mobile_country_code':
        echo get_country_code($user_id, 'mobile_country_code');
        break;

    case 'send_twilio_test':
        send_twilio_test_sms($user_id, $mobile_country_code);
        break;

    case 'reroute_to_tabsms':
        reroute_to_tabsms();
        break;
    
    case 'send_twilio_test_config':
        send_twilio_test_sms_config($user_id, $sid, $token, $twilio_country_code, $twilio_phone_number, $twilio_test_country_code, $test_twilio_phone);
        break;

    case 'config_authentication':
        authenticate($user_id, $sid, $token);
        break;

    default:
        echo 'Unknown mode';
        break;
    }
}


/**
 * Sends a vkey to the user to put into XI to verify
 * the phone number entered
 *
 * @param   int     $user_id    User ID, if 0 use session user_id (optional)
 * @return  bool                True if sent successfully
 */
function send_twilio_user_phone_vkey($user_id, $mobile_country_code)
{
    // get settings
    $settings = get_option('twilio_options');
    if (empty($settings)) {
        echo "Settings could not be loaded";
        return;
    }
    else {
        $settings = unserialize($settings);
    }

    $account_sid = grab_array_var($settings, 'sid', '');
    $auth_token = grab_array_var($settings, 'auth_token', '');
    $twilio_country_code = grab_array_var($settings, 'twilio_country_code');
    $twilio_phone = grab_array_var($settings, 'twilio_phone', '');
    $mobile_number = get_user_meta($user_id, 'mobile_number');
    $client = new Client($account_sid, $auth_token); 
 
    // validate user input
    if (empty($twilio_country_code)) {
        echo "Twilio country code is empty";
        return;
    }
    if (empty($twilio_phone)) {
        echo "Twilio phone is empty";
        return;
    }
    if (strlen($twilio_phone) <= 3) {
        echo "Twilio phone needs a country code";        
        return;
    }
    if (empty($mobile_country_code)) { 
        echo "Mobile country code is empty";
        return;
    }
    if (empty($mobile_number)) { 
        echo "Mobile number is empty";
        return;
    }
    if (strlen($mobile_number) <= 3) {
        echo "Mobile number needs a country code";
        return;
    }
    if (is_user_phone_verified($user_id)) { 
        echo "User phone is already verified";
        return;
    }  

    // format phone numbers
    $twilio_phone = "+" . $twilio_country_code . $twilio_phone;
    $mobile_number = "+" . $mobile_country_code . $mobile_number;

    // Generate a new key
    $key = sprintf("%05d", mt_rand(1, 99999));
    set_user_meta($user_id, 'phone_key', $key);
    $message = _("Mobile Phone Verification key: ") . $key;

    // Send the key
    try {
        $client->messages->create(
            $mobile_number,
            array(
                'from' => $twilio_phone,
                'body' => $message
            )
        );
    } 
    catch (Exception $e) {
        $message = $e->getMessage();
        if (strpos($message, 'To') !== false) {
            echo "Test phone number is invalid.";
        } 
        elseif (strpos($message, 'From') !== false) {
            echo "Twilio phone number is invalid.";
        } 
        elseif (strpos($message, 'unverified') !== false) {
            echo "Test phone number is unverified on Twilio. You can only send messages to verified numbers using a trial account.";
        } 
        elseif (strpos($message, 'Authenticate') !== false) {
            echo "Authentication failed. Please make sure your SID and token are correct.";
        }
        elseif (strpos($message, 'HTTP 404') !== false) {
            echo "Authentication failed. Please make sure your SID and token are correct.";
        }
        else {
            echo $message;
        }
        set_user_meta($user_id, 'phone_key', '');
        return;
    }

    // Key expires in 10 minutes
    $expires = time() + (60 * 10);
    set_user_meta($user_id, 'phone_key_expires', $expires);
    
    echo "Success!";
}


/**
* Verify the user input against the actual key
*/
function verify_twilio_phone_vkey($user_id, $user_twilio_key)
{
    // retrieve valid values
    $key = get_user_meta($user_id, 'phone_key');
    $expires = get_user_meta($user_id, 'phone_key_expires'); 

    // input validation
    if (empty($key)) {
        echo 'Verification Key is not specified';
    }
    if (empty($user_twilio_key)) {
        echo 'User input key is not specified';
    }
    if ( empty($expires) || ($expires < time()) ) {
        echo 'Time has expired';    
    }    
    
    // Check validation
    if (($key == $user_twilio_key) && ($expires > time()) ) {
        set_user_meta($user_id, 'phone_verified', 1);
        set_user_meta($user_id, 'phone_key', '');
        set_user_meta($user_id, 'phone_key_expires', '');
        
        echo 'Verification successful!';
        return true; 
    }

    echo 'Verification unsuccessful!';
    return false;
}

/**
* Get the verification tag icon for every stage
*/
function get_user_twilio_phone_vtag($user_id=1) 
{
    // default values
    $fa = 'fa-question';
    $text = _('Phone Number Unspecified');

    // retrieve user values
    $phone = get_user_meta($user_id, 'mobile_number', '');
    $vkey = get_user_meta($user_id, 'phone_key', '');
    $expires = get_user_meta($user_id, 'phone_key_expires', '');

    // if already verified
    if (is_user_phone_verified($user_id)) {
        $fa = 'fa-check';
        $text = _("Verified Number");
    }
    // if unverified
    else if (!empty($vkey)) {
        if (!empty($expires) && $expires < time()) {
            $fa = 'fa-exclamation';
            $text = _("Phone Number Unverified");
        }
        // if being verified 
        else {
            $fa = 'fa-spinner';
            $text = _("Verification in Progress");
        }
    // if unverified
    } else if (!empty($phone)) {
            $fa = 'fa-exclamation';
            $text = _("Phone Number Unverified");
    }

    // create the icon
    $output = '<i title="'.$text.'" class="fa tt-bind fa-fw fa-14 '.$fa.'"></i>';

    // send the icon
    echo $output;
}

/**
* Get the expire time of the key
*/
function twilio_countdown($user_id) 
{
    // get remaining time
    $time_left = get_user_meta($user_id, 'phone_key_expires');

    // check if key is expired
    if (($time_left < time()) || empty($time_left) ) {
        echo _('Key has expired.');
    }
    // otherwise show the remaining time
    else {
        $remaining_time = get_user_phone_vkey_expire($user_id);
        echo "Key expires in <strong>" . $remaining_time . "</strong>";        
    }
}

/**
* Country code setter
*/
function save_country_code($user_id, $country_code, $key)
{
    // clear text
    $country_code = preg_replace('/\D/', '', $country_code);    

    // save country code
    set_user_meta($user_id, $key, $country_code);
}


/**
* Country code getter
*/
function get_country_code($user_id, $key)
{
    return get_user_meta($user_id, $key, '');
}


/**
 * Sends a test sms notification to the user mobile number
 *
 * @param   int     $user_id    User ID, if 0 use session user_id (optional)
 * @return  bool                True if sent successfully
 */
function send_twilio_test_sms($user_id, $mobile_country_code)
{
    // get settings
    $settings = get_option('twilio_options');
    if (empty($settings)) {
        echo "Settings could not be loaded";
        return;
    }
    else {
        $settings = unserialize($settings);
    }

    $account_sid = grab_array_var($settings, 'sid', '');
    $auth_token = grab_array_var($settings, 'auth_token', '');
    $twilio_country_code = grab_array_var($settings, 'twilio_country_code', '');
    $twilio_phone = grab_array_var($settings, 'twilio_phone', '');
    $mobile_number = get_user_meta($user_id, 'mobile_number');
    $client = new Client($account_sid, $auth_token); 
 
    // validate user input
    if (empty($twilio_country_code)) {
        echo "Twilio country code is empty";
        return;
    }
    if (empty($twilio_phone)) {
        echo "Twilio phone is empty";
        return;
    }
    if (strlen($twilio_phone) <= 3) {
        echo "Twilio phone needs a country code";        
        return;
    }
    if (empty($mobile_country_code)) { 
        $mobile_country_code = 1;
    }
    if (empty($mobile_number)) { 
        echo "Mobile number is empty";
        return;
    }
    if (strlen($mobile_number) <= 3) {
        echo "Mobile number is invalid";
        return;
    }

    // format phone numbers
    $twilio_phone = "+" . $twilio_country_code . $twilio_phone;
    $mobile_number = "+" . $mobile_country_code . $mobile_number;

    $message = _("This is a test notification sent from Nagios XI.");

    // Send the test notification
    try {
        $client->messages->create(
            $mobile_number,
            array(
                'from' => $twilio_phone,
                'body' => $message
            )
        );
    } 
    catch (Exception $e) {
        $message = $e->getMessage();
        if (strpos($message, 'To') !== false) {
            echo "Mobile phone number is invalid.";
        } 
        elseif (strpos($message, 'From') !== false) {
            echo "Twilio phone number is invalid.";
        } 
        elseif (strpos($message, 'unverified') !== false) {
            echo "Mobile phone number is unverified on Twilio. You can only send messages to verified numbers using a trial account.";
        } 
        elseif (strpos($message, 'Authenticate') !== false) {
            echo "Authentication failed. Please make sure your SID and token are correct.";
        }
        elseif (strpos($message, 'HTTP 404') !== false) {
            echo "Authentication failed. Please make sure your SID and token are correct.";
        }
        else {
            echo $message;
        }
        return;
    }

    echo "Success!";
}

function reroute_to_tabsms()
{
    echo header("Location:".get_base_url()."account/notifymethods.php");
}


/**
 * Sends a test sms notification to the user mobile number
 *
 * @param   int     $user_id    User ID, if 0 use session user_id (optional)
 * @return  bool                True if sent successfully
 */
function send_twilio_test_sms_config($user_id, $sid, $token, $twilio_country_code, $twilio_phone_number, $twilio_test_country_code, $test_twilio_phone)
{
    $sid = preg_replace("/[^a-zA-Z0-9]+/", "", $sid);
    $token = preg_replace("/[^a-zA-Z0-9]+/", "", $token);
    $twilio_phone_number = preg_replace('/\D/', '', $twilio_phone_number);
    $test_twilio_phone = preg_replace('/\D/', '', $test_twilio_phone);

    $client = new Client($sid, $token); 
 
    // validate user input
    if (empty($twilio_country_code)) {
        echo "Twilio country code is empty";
        return;
    }
    if (empty($twilio_phone_number)) {
        echo "Twilio phone number is empty";
        return;
    }
    if (strlen($twilio_phone_number) <= 3) {
        echo "Twilio phone number needs a country code";        
        return;
    }
    if (empty($twilio_test_country_code)) { 
        $mobile_country_code = 1;
    }
    if (empty($test_twilio_phone)) { 
        echo "Test phone number is empty";
        return;
    }
    if (strlen($test_twilio_phone) <= 3) {
        echo "Test phone number needs is invalid";
        return;
    }

    // format phone numbers
    $twilio_phone_number = "+" . $twilio_country_code . $twilio_phone_number;
    $test_twilio_phone = "+" . $twilio_test_country_code . $test_twilio_phone;

    $message = _("This is a test notification sent from Nagios XI.");

    // Send the test notification
    try {
        $client->messages->create(
            $test_twilio_phone,
            array(
                'from' => $twilio_phone_number,
                'body' => $message
            )
        );
    } 
    catch (Exception $e) {
        $message = $e->getMessage();
        if (strpos($message, 'To') !== false) {
            echo "Test phone number is invalid.";
        } 
        elseif (strpos($message, 'From') !== false) {
            echo "Twilio phone number is invalid.";
        } 
        elseif (strpos($message, 'unverified') !== false) {
            echo "Test phone number is unverified on Twilio. You can only send messages to verified numbers using a trial account.";
        } 
        elseif (strpos($message, 'Authenticate') !== false) {
            echo "Authentication failed. Please make sure your SID and token are correct.";
        }
        elseif (strpos($message, 'HTTP 404') !== false) {
            echo "Authentication failed. Please make sure your SID and token are correct.";
        }
        else {
            echo $message;
        }
        return;
    }

    echo "Success!";
}

function authenticate($user_id, $sid, $token)
{
    $url = 'https://api.twilio.com/2010-04-01/Accounts';

    $process = curl_init();
    curl_setopt($process, CURLOPT_URL, $url);
    curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($process, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($process, CURLOPT_USERPWD, $sid . ":" . $token);
    curl_setopt($process, CURLOPT_TIMEOUT, 10);

    $result = curl_exec($process);
    curl_close($process);

    $result = new SimpleXMLElement($result);

    if (isset($result->RestException)) {
        echo $result->RestException->Detail;
        return;
    }

    if (isset($result->Accounts)) {
        foreach ($result->Accounts->Account as $account) {
            if ($account->Status == 'active') {
                echo "Success!";
                return;
            }
        }
    }    
    
    echo "Oops! Something went wrong!";
}
