<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of BizLayer
 *
 * @author dghai
 */
require_once 'ErrorObject.php';
require_once 'Dao.php';

class BizLayer
{
    //this is needed to make sure arbitrary code is not executed.
    //functionName => number_of_arguments
    private $_functionRegistry;
    private $_functionRegistry_arrayCalls;
    private $_dao;
    private $_requestObject;
    
    function __construct($request)
    {
        $this->_dao = new Dao($request);
        //return error object if connection to DB failed.
        if($this->_dao instanceof ErrorObject)
        {
            return $this->_dao;
        }
        
        $this->_requestObject = $request;
        
        //values for methods will be one less here as we are adding request's
        //hash value in function call for purposes of the application.
        //Basically value here indicates how many values should the client pass.
        $this->_functionRegistry = array
                (
            "IsAuthorizedUser"      => 3,
            "GetQuestions"          => 1,
            "GetAges"               => 0,
            "GetWeights"            => 0,
            "SetNewUserInfo"        => 3,
            "IsUsernameAvailable"   => 1,
            "UpdateUserInfo"        => 11,
            "GetCarModel"           => 2,
            "GetPreviousAnswers"    => 1,
            "SetNewSurvey"          => 3,
            "SetEndSurvey"          => 1,
            "ResetPassword"         => 1,
            "ChangePassword"        => 3,
            "GetBadges"             => 1,
            "SetBadges"             => 2,
            
                );
        
        $this->_functionRegistry_arrayCalls = array
                (
            "SetAnswers"            => 'answersArray',
                );
    }
    
//    private function GetSurveysForUser($loginId)
//    {
//        $allSurveys = $this->_dao->GetSurveysForUser($loginId);
//        if(!is_array($allSurveys))
//        {
//            //if this is not an array, then it simply means its an error. return that.
//            return $allSurveys;
//        }
//        //send only 3 latest surveys of the surveys that the user has already taken
//        $numTakenSurveys = 0;
//        $surveys = array();
//        foreach ($allSurveys as $key=>$value)
//        {
//            if($value->survey_id > 0 && $numTakenSurveys < 3)
//            {
//                array_push ($surveys, $value);
//                $numTakenSurveys++;
//            }
//            else if($value->survey_id == -1)
//                array_push ($surveys, $value);
//        }
//        return $surveys;
//    }
    
    function IsAuthorizedUser($hash, $username, $isAdmin, $password)
    {
        $retval = $this->_dao->IsUserAuthorized($username, $password, $isAdmin);
        if(!($retval instanceof Users))
        {
            //check if the user is admin
            $retval = $this->_dao->IsUserAdmin($username, $password);
            $_SESSION[$hash] = $retval;
            return;
        }
        $badges = $this->_dao->GetBadges($username);
        //suppress error when retrieving badges. 
        //Client wont be checking for nested server errors.
        $retval->badges = $badges instanceof ErrorObject ? array() : $badges;
        
        //same for surveys that a user has
        $surveys = $this->_dao->GetSurveysForUser($username);
        $retval->surveys = $surveys instanceof ErrorObject ? array() : $surveys;
        $_SESSION[$hash] = $retval;
    }
    
    function ChangePassword($hash, $username,  $newPassword,  $oldPassword)
    {
        require_once 'DbTables.php';
        $authorizedUser = $this->_dao->IsUserAuthorized($username, $oldPassword, false);
        if($authorizedUser instanceof Users)
        {
            $_SESSION[$hash] = $this->_dao->SetNewPassword($username, $newPassword);
            return;
        }
        
        $_SESSION[$hash] = $authorizedUser;
    }
    
    public function GetQuestions($hash, $surveyId)
    {
        $retval = $this->_dao->GetSurveyQuestions($surveyId);
        $_SESSION[$hash] = $retval;
    }
    
    public function SetAnswers($hash, array $answersArray)
    {
        $retval = $this->_dao->SetAnswers($answersArray);
        $_SESSION[$hash] = $retval;
    }
    
    public function GetAges($hash)
    {
        $retval = $this->_dao->GetAgeRanges();
        $arrayAges = array();
        foreach($retval as $key=>$value)
        {
            $arrayAges []= $value->age_from.' to '.$value->age_to;
        }
        $_SESSION[$hash] = $arrayAges;
    }
    
    public function GetWeights($hash)
    {
        $retval = $this->_dao->GetWeightRanges();
        $arrayWeights = array();
        foreach($retval as $key=>$value)
        {
            $arrayWeights []= $value->weight_from.' to '.$value->weight_to;
        }
        $_SESSION[$hash] = $arrayWeights;
    }
    
    public function IsUsernameAvailable($hash, $username)
    {
        $retval = $this->_dao->IsUsernameAvailable($username);
        $_SESSION[$hash] = $retval;
    }

    public function SetNewUserInfo($hash, $username, $email, $password)
    {
        $_SESSION[$hash] = $this->_dao->SetNewUserInfo($username, $password, $email);
    }
    
    public function UpdateUserInfo($hash, $sittingHeight, $weightRange, 
            $upperLegLength, $shirtSize, $gender, $zip, $email, $ageRange, 
            $height, $shoeSize, $userid)
    {
        $_SESSION[$hash] = $this->_dao->UpdateUserInfo(
                                                        $userid, 
                                                        $email, 
                                                        $zip, 
                                                        $height, 
                                                        $sittingHeight, 
                                                        $upperLegLength, 
                                                        $weightRange, 
                                                        $ageRange, 
                                                        $gender, 
                                                        $shirtSize, 
                                                        $shoeSize
                                                      );
    }

    function GetCarModel($hash, $year, $make)
    {
        $_SESSION[$hash] = $this->_dao->GetCarModel($make, $year);
    }
    
    function GetPreviousAnswers($hash, $activeSurveyId)
    {
        $_SESSION[$hash] = $this->_dao->GetPreviousAnswers($activeSurveyId);
    }

    function SetNewSurvey($hash, $vehicleId, $questionSet_id, $userId)
    {
        $_SESSION[$hash] = $this->_dao->SetNewSurvey($vehicleId, $questionSet_id, $userId);
    }
    
    private function SetEndSurvey($surveyId)
    {
        $_SESSION[$hash] = $this->_dao->SetEndSurvey($surveyId);
    }
    
    private function GeneratePassword()
    {
        $newPassLength = rand(5, 10);
        $newPass = '';
        for($i = 0; $i<$newPassLength; $i++)
        {
            $newPass = $newPass.chr(rand(97, 122));
        }
        return $newPass;
    }
    
    private function EmailNewPassword($username, $toEmailId, $newPassword)
    {
        //from dataendpoint.php
        global $config;
        $webmaster_email = $config->GetWebmasterEmail();
        $htmlEmail = strtr($config->GetResetPasswordEmailTemplate() , array(
                            '{username}'        => $username,
                            '{password}'        => $newPassword,
                            '{webmaster_email}' => $webmaster_email,
                        )
                      );
        $plaintextEmail = strtr($config->GetResetPasswordEmailPlaintextTemplate() , array(
                            '{username}'        => $username,
                            '{password}'        => $newPassword,
                            '{webmaster_email}' => $webmaster_email,
                        )
                      );
                
        require_once 'Base/src/ezc_bootstrap.php';
        // Create a new mail composer object
        $mail = new ezcMailComposer();
        // Specify the "from" mail address
        $mail->from = new ezcMailAddress( $config->GetWebmasterEmail(), $config->GetWebmasterName() );
        // Add one "to" mail address (multiple can be added)
        $mail->addTo( new ezcMailAddress( $toEmailId, 'Guest' ) );
        // Specify the subject of the mail
        $mail->subject = $config->GetResetPasswordEmailSubject();
        // Specify the body text of the mail
        $mail->plainText = $plaintextEmail;
        $mail->htmlText = $htmlEmail;
        // Generate the mail
        $mail->build();
        // Create a new SMTP transport object with an SSLv3 connection.
        // The port will be 465 by default, use the 4th argument to change it.
        // Username and password (2nd and 3rd arguments) are left blank, which means
        // the mail host does not need authentication.
        // The 5th parameter is the $options object which specifies a SSLV3 connection
        // (default is ezcMailSmtpTransport::CONNECTION_PLAIN).
        $options = new ezcMailSmtpTransportOptions();
        $options->connectionType = ezcMailSmtpTransport::CONNECTION_SSLV3;
        $transport = new ezcMailSmtpTransport( $config->GetSMTPServer(),
                                               $config->GetSMTPUsername(), 
                                               $config->GetSMTPPassword(), 
                                               $config->GetSMTPPort(), 
                                               $options );
        // The option can also be specified via the option property:
        $transport->options->connectionType = ezcMailSmtpTransport::CONNECTION_SSLV3;
        // Use the SMTP transport to send the created mail object
        try
        {
            $transport->send( $mail );
            return true;
        }
        catch (ezcMailTransportException $e)
        {
            return false;
        }
    }

    public function ResetPassword($hash, $loginId)
    {
        $toEmail = $this->_dao->GetEmailForLoginId($loginId);
        if($toEmail instanceof ErrorObject || $toEmail === false)
        {
            $_SESSION[$hash] = $toEmail;
            return;
        }
        $newPassword = $this->GeneratePassword();
                
        $isUpdateSuccessful = $this->_dao->SetNewPassword($loginId, $newPassword);
        if($isUpdateSuccessful instanceof ErrorObject || $isUpdateSuccessful === false)
        {
            $_SESSION[$hash] = $isUpdateSuccessful;
            return;
        }
        $_SESSION[$hash] = $this->EmailNewPassword($loginId, $toEmail, $newPassword);
        
    }
    
    public function GetBadges($hash, $loginId)
    {
        $_SESSION[$hash] = $this->_dao->GetBadges($loginId);
    }
    
    public function SetBadges($hash, $userid, array $badgesArray)
    {
        //Database Programmer:
        //On Ipad, all badges are retrieved, stored in a collection, new badges
        //earned are added to that collection and that is sent back at the end
        //of the survey. To prevent infinite badges being added for the user,
        //I need to first check badges they already had and then insert the new
        //ones only. I am not deleting all badges of the user first and then
        //inserting all of them because that would require delete privileges,
        //which I have not given to the user for security purposes.
        //
        //IPad Programmer:
        //and its cruch time and the ipad programmer went crazy...
        //
        //Databse Programmer:
        //Yeah... that too! :D
        
        $previousBadges = $this->_dao->GetBadges($userid);
        $newBadges = array_diff($badgesArray, $previousBadges);
        $_SESSION[$hash] = $this->_dao->SetBadges($userid, $newBadges);
    }
    //returns response obj
    function CallFunction()
    {
        $functionCall = $this->_requestObject->call;
        //copy argument array
        $functionArguments = array();
        $functionArguments['hash'] = $this->_requestObject->requestHash;
        
        //if its an unregistered call, return an error
        if(array_key_exists($functionCall, $this->_functionRegistry))
        {
            foreach(array_keys($this->_requestObject->paramArray) as $key)
            {
                $functionArguments[$key] = $this->_requestObject->paramArray[$key];
            }
        }
        else if(array_key_exists($functionCall, $this->_functionRegistry_arrayCalls))
        {
            $functionArguments[$this->_functionRegistry_arrayCalls[$functionCall]] = $this->_requestObject->paramArray;
        }
        else
        {
            $this->_dao->CloseConnection();
            return new ErrorObject($this->_requestObject, E_VROOM_INVALID_FUNCTION_CALL);
        }
        //just check if we are sending any error. if yes, then mark it as an error
        call_user_func_array(array($this, $functionCall), $functionArguments);
        
        //need to use hashes because call_user_func_array makes a new instance
        //of the class being called and hence not returning a value.
        
        $responseData = $_SESSION[$this->_requestObject->requestHash];
        unset($_SESSION[$this->_requestObject->requestHash]);
        $response = new ResponseObject(
                                        $this->_requestObject->requestHash, 
                                        $responseData, 
                                        $responseData instanceof ErrorObject
                                      );
        //close the db connection once the request has been served
        $this->_dao->CloseConnection();
        
        return $response;
    }
}

?>
