<?php

require_once 'modules/admin/views/public/SignupView.php';
require_once 'newedge/classes/NE_PluginCollection.php';
require_once 'modules/clients/models/UserGateway.php';

/**
 * @package Admin
 *
 * This file has no template. It is merely used to process the signup request
 * and to handle things like Fraud, Payment Processor sendoff etc.
*/
class ViewSignup_Process extends SignupView
{
    var $permission     = '';
    var $signupChecksPassed = true;
    var $signupExistingUser = false;
    var $existingUserId = null;
    var $signupLogLevel = 2;

    function dispatch()
    {

        $this->initialize();
        $this->currencys = new Currency($this->user);

        // Start logging
        $this->log($this->signupLogLevel, "******* NEW SIGNUP IS STARTING *******");
        $this->log($this->signupLogLevel, "Signup: STARTING PROCESSING");


        // Do we have an existing logged in user?
        if($this->user->getEmail() != '' && !$this->user->isAdmin()) {
            $this->signupExistingUser = true;
            $this->log($this->signupLogLevel, "Signup: Existing logged in user found. Email: '".$this->user->getEmail()."'. User ID:'".$this->user->getId()."'");
        }

        // Validate the credentials of the existing user if one is logging in
        if(@$_REQUEST['userSelection'] == 'existing') {

            $this->tplView->validatingExisting = true;

            $error = $this->validateUserLoggingIn(@$_REQUEST['existingEmail'], @$_REQUEST['existingPassword']);
            if(@$error) {
                $this->failedValidation($error);
                return;
            }

            $this->log($this->signupLogLevel, "Signup: User logged in via Signup. E-mail: '".$_REQUEST['existingEmail']."'");
        }

        if(!$this->signupExistingUser) {
            $this->log($this->signupLogLevel, "Signup: New user is signing up.");
        }

        // Before we do anything, validate the captcha
        if($this->settings->get('Request Access Code') == 1 && !$this->signupExistingUser && !isset($_POST['phoneCalled'])) {
            if($this->validateRecaptcha() == false) {

                $this->log($this->signupLogLevel, "Signup: Capatch Failed! Done.");

                // Send back to step 4
                $this->failedValidation($this->lang("The verification code you entered was invalid."));
                return;
            }

            $this->log($this->signupLogLevel, "Signup: Capatch Verified");
        }


        /*
         * WE NEED TO HANDLE FIELD VALIDATION HERE AND SEND USERS BACK IF WE HAVE ISSUES
         * TODO: FIELD VALIDATION
         *
         * Email Duplicates
         * Password Strength policy (try and move to jQuery)
         * Credit Card Number (if required)
         *
         */

        // Validate Credit Card Number
        if (!$this->signupExistingUser && isset($_REQUEST['paymentMethod']) && isset($_REQUEST[$_REQUEST['paymentMethod'].'_ccNumber'])) {
            $cards = array();
            if(!is_null($this->settings->get("plugin_".$_REQUEST['paymentMethod']."_Visa")) && $this->settings->get("plugin_".$_REQUEST['paymentMethod']."_Visa") == 1){
                $cards['VISA'] = 'Visa';
            }
            if(!is_null($this->settings->get("plugin_".$_REQUEST['paymentMethod']."_MasterCard")) && $this->settings->get("plugin_".$_REQUEST['paymentMethod']."_MasterCard") == 1){
                $cards['MC'] = 'MasterCard';
            }
            if(!is_null($this->settings->get("plugin_".$_REQUEST['paymentMethod']."_AmericanExpress")) && $this->settings->get("plugin_".$_REQUEST['paymentMethod']."_AmericanExpress") == 1){
                $cards['AMEX'] = 'American Express';
            }
            if(!is_null($this->settings->get("plugin_".$_REQUEST['paymentMethod']."_Discover")) && $this->settings->get("plugin_".$_REQUEST['paymentMethod']."_Discover") == 1){
                $cards['DISC'] = 'Discover';
            }
            if(!is_null($this->settings->get("plugin_".$_REQUEST['paymentMethod']."_LaserCard")) && $this->settings->get("plugin_".$_REQUEST['paymentMethod']."_LaserCard") == 1){
                $cards['LASER'] = 'LaserCard';
            }
            if(!is_null($this->settings->get("plugin_".$_REQUEST['paymentMethod']."_DinersClub")) && $this->settings->get("plugin_".$_REQUEST['paymentMethod']."_DinersClub") == 1){
                $cards['DINERS'] = 'Diners Club';
            }
            if(!is_null($this->settings->get("plugin_".$_REQUEST['paymentMethod']."_Switch")) && $this->settings->get("plugin_".$_REQUEST['paymentMethod']."_Switch") == 1){
                $cards['SWITCH'] = 'Switch';
            }
            $cardtype = 'UNKNOW';

            foreach($cards AS $cardKey => $card){
                $errornumber = '';
                $errortext   = '';

                require_once 'modules/billing/phpcreditcard.php';
                if(checkCreditCard($_REQUEST[$_REQUEST['paymentMethod'].'_ccNumber'], $card, $errornumber, $errortext)){
                    $cardtype = $cardKey;
                    break;
                }
            }

            if ($cardtype == 'UNKNOW') {
                $message = $this->lang("Invalid Credit Card Number");
                $this->log($this->signupLogLevel, "Signup: Credit Card Number failed. Reason: '$message'. Done.");

                // Fail due to Credit Card Number
                $this->failedValidation($message);
                return;
            }

            $this->log($this->signupLogLevel, "Signup: Validated Credit Card Number Successfully.");
        }

        // Validate password
        if ($this->settings->get('Enforce Password Strength in Signup') || $this->settings->get('Enforce Password Strength For Domains')) {
            include_once 'modules/admin/models/PasswordStrength.php';
            $passwordStrength = new PasswordStrength($this->settings);

            // no need to check existing users passwords
            if ($this->settings->get('Enforce Password Strength in Signup') && !$this->signupExistingUser) {
                $passwordStrength->setPassword($_REQUEST['password']);
                if (!$passwordStrength->validate()) {
                    foreach ($passwordStrength->getMessages() as $message) {

                        $this->log($this->signupLogLevel, "Signup: Password strength failed. Reason: '$message'. Done.");

                        // Fail due to password
                        $this->failedValidation($message);
                        return;
                    }
                }

                $this->log($this->signupLogLevel, "Signup: Validated Password Successfully.");
            }
        }

        // Validate email
        if (!$this->signupExistingUser) {

			// Before we make any transactions with the database, let's validate the email address.

            $emailId = $this->user->getCustomFieldsObj()->_getCustomFieldIdByType(typeEMAIL);

			// Don't know why we are trying to suppress anything, but OK!
			$email = htmlspecialchars(@$_REQUEST["CT_$emailId"], ENT_QUOTES);
			if ( !NE_Lib::valid_email($email) )
			{
                $this->log($this->signupLogLevel, "Signup: Email address provided is not valid.");

				$this->failedValidation("Email address provided is not valid.");
				return;
			}

            $userGateway = new UserGateway();
            try{
                $verify = $userGateway->VerifyEmailDuplicate(htmlspecialchars(@$_REQUEST["CT_$emailId"], ENT_QUOTES), true);
            } catch (Exception $ex) {

                $this->log($this->signupLogLevel, "Signup: New user duplicate email failed. Message '".$ex->getMessage()."'. Done.");

                // Fail due to email
                $this->failedValidation($ex->getMessage());
                return;
            }

            if($userGateway->SupportEmailExist(htmlspecialchars(@$_REQUEST["CT_$emailId"], ENT_QUOTES))){
                $gAlertMessage = $this->lang("The E-mail %s can not be used because it is already in use for support by another user.", htmlspecialchars(@$_REQUEST["CT_$emailId"], ENT_QUOTES));
                $this->log($this->signupLogLevel, "Signup: New user duplicate email failed. Message '".$gAlertMessage."'. Done.");

                // Fail due to email
                $this->failedValidation($gAlertMessage);
                return;
            }

            $this->log($this->signupLogLevel, "Signup: New user duplicate email OK.");
		}

        // Check fraud plugins
        if (!$this->signupExistingUser) {
            $fraudPlugins = new NE_PluginCollection("fraud", $this->user);
            while ($fraudPlugin = $fraudPlugins->getNext()) {
                if (!$this->settings->get('plugin_'.$fraudPlugin->getInternalName()."_Enabled")) {
                    continue;
                }

                $this->log($this->signupLogLevel, "Signup: Calling Fraud Plugin: ".$this->settings->get("plugin_".$fraudPlugin->getInternalName()."_Plugin Name"));

                $fraudPlugin->grabDataFromRequest($_REQUEST);
                $fraudCheckResult = $fraudPlugin->execute();

                $outputkeys = array_keys($fraudCheckResult);
                $numoutputkeys = count($fraudCheckResult);
                $fraudmsg = array();
                for ($i = 0; $i < $numoutputkeys; $i++) {
                     $key = $outputkeys[$i];
                     $value = $fraudCheckResult[$key];
                     $fraudmsg[] = $key . " = " . $value;
                }

                // post the fraud score for use in the phone verification step
                $_POST['fraudScore'] = $fraudPlugin->getScore();

                $fraudPlugin->extraSteps();

                if (!$fraudPlugin->isOrderAccepted()) {
                    $failureString = "";
                    if(is_array($fraudPlugin->getFailureMessages())) {
                        foreach($fraudPlugin->getFailureMessages() AS $key) {
                            $failureString .= $key."<br>";
                        }
                    }

                    $this->log($this->signupLogLevel, "Signup: FRAUD FAILED. Reason '$failureString'. Done.");

                    $this->failedValidation($failureString);
                    return;
                    //$arrError = array_merge($arrError, $fraudPlugin->getFailureMessages());
                }
                if ( count($fraudmsg) > 0 ) {
                    $_SESSION['fraudmsg'] = $fraudmsg;
                }
                $this->log($this->signupLogLevel, "Signup: Fraud Passed");
            }
        }

        // Check Phone Plugins
        if (!$this->signupExistingUser && !isset($_POST['phoneCalled'])) {

            $phoneVerificationPlugins = new NE_PluginCollection('phoneverification', $this->user);

            // Get the cart summary
            $cartSummary = $this->getCartSummary();

            // Find a plugin
            while ($phoneVerificationPlugin = $phoneVerificationPlugins->getNext(false)) {

                if ($this->settings->get("plugin_{$phoneVerificationPlugin}_Enabled") == 1 && $this->settings->get("plugin_{$phoneVerificationPlugin}_Minimum Bill Amount to Trigger Telephone Verification") <= @$cartSummary['total']['truePrice']) {

                    // Log the attempt
                    $this->log($this->signupLogLevel, "Signup: Calling Telephone Verification Fraud Plugin: ".$phoneVerificationPlugin." Invoice total is: ".@$cartSummary['total']['truePrice']);

                    require 'modules/admin/views/public/Signup_PhoneVerification.php';
                    ViewSignup_PhoneVerification::dispatch();
                    return;
                }
            }
        } else {
        	$this->log($this->signupLogLevel, "Signup: Phone verification not needed or already passed.");
		}	

        $this->log($this->signupLogLevel, "Signup: All checks passed.");

        // If we are still here then we passed validations and we don't have any phone
        // verifications to handle. So silently move on to creating accounts.
        $_REQUEST['signupChecksPassed'] = $this->signupChecksPassed;
        include("modules/admin/views/public/Signup_CreateAccounts.php");
        ViewSignup_CreateAccounts::dispatch($this->existingUserId);



    }

    /*
     * Function to validate the ReCaptcha
     */
    function validateRecaptcha() {

        require_once('modules/clients/recaptchalib.php');
        if($this->settings->get('ReCaptcha Private Key') != "") {
            $privatekey = $this->settings->get('ReCaptcha Private Key');
        } else {
            $privatekey = "6LdjHLwSAAAAACoiITbxNxAH31zQf3bQwF8-TqbY"; // Use ours if none set
        }
        $resp = recaptcha_check_answer ($privatekey,
                                    $_SERVER["REMOTE_ADDR"],
                                    @$_REQUEST["recaptcha_challenge_field"],
                                    @$_REQUEST["recaptcha_response_field"]);

        if (!@$resp->is_valid && @$_REQUEST["recaptcha_challenge_field"]) {
            // What happens when the CAPTCHA was entered incorrectly
            return false;
        } else {
            // Your code here to handle a successful verification
            return true;
        }
    }

    /*
     * Function to run if we failed a validation check.
     * Passes back relevant fields and sends you packing
     */
    function failedValidation($reason) {

        // Set old fields
        $_REQUEST['oldFields'] = $_REQUEST;
        $_REQUEST['errorReason'] = $reason;

        // Send back to step 4
        include("modules/admin/views/public/Signup_4_YourInfo.php");
        ViewSignup_4_YourInfo::dispatch();
        return;

    }

    /**
     * Function to validate the user that is logging in from signup
     */
    function validateUserLoggingIn($emailAddress, $password) {

        // Load the class
        require_once 'modules/clients/models/user.php';
        $allowedStatus = array(USER_STATUS_ACTIVE, USER_STATUS_INACTIVE, USER_STATUS_PENDING, USER_STATUS_CANCELLED);

        // Check for empty fields
        if(empty($emailAddress) || empty($password)) {
            return $this->lang('Invalid login information, please ensure that you fill out all fields');
        }

        // Start validating the user
        $query = 'SELECT userid '
                .'FROM user_customuserfields uc '
                .'LEFT JOIN customuserfields c ON uc.customid=c.id '
                .'WHERE uc.value=? AND c.type=? AND c.company_id=?';
        $result = $this->db->query($query, $emailAddress, typeEMAIL, NE_Registry::getCompany()->getId());
        list($tUserID) = $result->fetch();

        // User wasn't found, check domain access
        if (!isset($tUserID)) {
            // try logging in with domain name
            if ($this->settings->get('Access Via Domain Username') != 1) {
                return $this->lang("The information you entered was invalid, please try again.");
            }
        }

        // Validate the password
        if (($version = $this->db->getVersion()) && strcmp($version, '4.1') >= 0) {
            $query = "SELECT id FROM users WHERE (password=PASSWORD(?) OR password=OLD_PASSWORD(?)) AND groupid=1 AND status IN(".implode(',', $allowedStatus).") AND id=?";
            $result = $this->db->query($query, $password, $password, $tUserID);
        } else {
            $query = "SELECT id FROM users WHERE password=PASSWORD(?) AND groupid=1 AND status IN(".implode(',', $allowedStatus).") AND id=?";
            $result = $this->db->query($query, $password, $tUserID);
        }
        list($tUserID) = $result->fetch();
        if ($tUserID>0) {

            $user = New User($tUserID);


            $_SESSION['userId'] = $tUserID;
            $_SESSION['user'] = $user;
            $_SESSION['groupId'] = $user->getGroupId();

            if (defined('SESSION_LOGIN') && SESSION_LOGIN) {
                $_SESSION['sessionUserName'] = $emailAddress;
                $_SESSION['sessionPassword'] = $password;
            }

            $user->setChatStatus(CHAT_STATUS_AVAILABLE);
            $user->setLastLogin(date('Y-m-d H:i:s'));
            $user->save();

            // Valid
            $this->signupExistingUser = true;
            $this->existingUserId = $tUserID;
        } else {

            // Invalid
            return $this->lang("The information you entered was invalid, please try again.");
        }

    }
}

?>
