<?php  

    namespace Extension\VisitorBlocker;

    use Application\Config;
    use Application\CrmPayload;
    use Application\CrmResponse;
    use Application\Session;
    use Application\Response;
    use Application\Request;
    use Exception;
    use Database\Connectors\ConnectionFactory;
    use DateTime;
    use DateInterval;
    use Application\Model\Configuration;
    use Application\Http;
    use Application\Registry;
    use Application\Helper\Provider;

    class VisitorBlocker {

        /*
         * var $config to store the Visitor block data.
         */
        private $config, $currentStepId, $currentPageType, $customerId;
        private $database, $table, $tableUpsell,$localTable;

        public function __construct() {
           
            $this->config = Config::extensionsConfig('VisitorBlocker');
            $this->currentStepId = (int) Session::get('steps.current.id');
            $this->currentPageType = Session::get('steps.current.pageType');
            $this->customerId = Session::get('steps.1.customerId');
            $this->database = STORAGE_DIR . DS . 'orderdecline.sqlite';
            $this->table = 'declinelogs';
            $this->tableUpsell = 'declinelogs_upsell';
            $this->localTable = 'repeat_orders_local';
            $this->ip = Request::getClientIp();
            $this->city = strtolower(Session::get('customer.shippingCity'));
            $this->zip = Session::get('customer.shippingZip');
            
            $this->configId      = (int) Session::get('steps.current.configId');
            try{
                $this->configuration = new Configuration($this->configId);
            } 
            catch (Exception $ex) {
    
            }
            $this->createTable();
        }

        public function init() {

            //check if Block engine is local or remote
            if(!strncmp($this->config['block_engine'], 'local', strlen('local'))) {
                $this->orderDecline();
            }
        }

        public function increaseDeclineCount() {
            
            if( Request::attributes()->get('action') === 'prospect' || empty($this->config['enable_order_decline_limit'])) {
                return;
            }
            
            if(strncmp($this->config['order_decline_type'], 'SQLite', strlen('SQLite'))) {
                return;
            }

            $response = CrmResponse::all();
            
            $allowPrepaid = Config::configurations(sprintf(
                '%s.accept_prepaid_cards', $this->configId
            ));
            
            if( preg_match("/Prepaid.+Not Accepted|Prepaid.+not allowed/i", $response['errors']['crmError']) && !empty($response['errors']['crmError']) && !empty($allowPrepaid)) {
                return;
            }
            
            if(empty($response['success']) && !empty($response['errors'])) {   
                
                $email = CrmPayload::get('email');
                $creditCardNumber = Request::form()->get('creditCardNumber');

                if(empty($creditCardNumber)) {
                    $creditCardNumber = Session::get('customer.cardNumber');
                }
                
                $creditCardNumber = $this->encryptData($creditCardNumber,'md5');
                $list = $this->getDbInfo($email, $creditCardNumber);
                
                if(!$list) {
                    //insert new
                    $blockTime = $this->config['default_block_time'];
                    $time = new DateTime();
                    $time->add(new DateInterval('PT0H' . $blockTime . 'M0S'));
                    $this->insert(array(
                        'email' => $email,
                        'max_block_time' => 1,
                        'last_decline_datetime' => $time->format("Y-m-d H:i:s"),
                        'ip_address' => Request::getClientIp(),
                        'previous_card' => $creditCardNumber
                    ));
                }
                else {
                    //update
                    $tempId = current($list)['id'];
                    $numberOfBlock = (int) current($list)['max_block_time'];
                    $this->update($tempId, array(
                        'max_block_time' => $numberOfBlock + 1,
                    ));
                }

                $customErrorMessage = $this->getCustomErrorMessage();

            if (!empty($response['declinePixels'])) {
                Response::send(array(
                    'success' => false,
                    'errors' => array(
                        'crmError' => !empty($customErrorMessage) ? $customErrorMessage : $response['errors']['crmError']
                    ),
                    'declinePixels' => $response['declinePixels'],
                    'isTrigger'  =>  true
                ));
            }

                Response::send(array(
                    'success' => false,
                    'errors' => array(
                        'crmError' => !empty($customErrorMessage) ? $customErrorMessage : $response['errors']['crmError']
                    )
                ));
            } 
            return;
        }

        private function getCustomErrorMessage()
        {
            $enable = Config::extensionsConfig('CbUtilityPackage.enable_custom_decline_msg');
            $declineMessages = Config::extensionsConfig('CbUtilityPackage.custom_decline_msg');
            if (!$enable)
            {
                return;
            }

            $response = CrmResponse::all();
        
            $mappedDeclineMsg = '';

            if (!empty($declineMessages) && !empty($response['errors']['crmError']) && !$response['success'])
            {
                $errorMsg = $response['errors']['crmError'];
                foreach ($declineMessages as $value)
                {
                    $crmDeclineMsg = $value['crm_msg'];
                    if (preg_match("/$errorMsg/i", $crmDeclineMsg) ||
                            preg_match("/$crmDeclineMsg/i", $errorMsg))
                    {
                        $mappedDeclineMsg = $value['custom_msg'];
                        break;
                    }
                }
                if (!empty($mappedDeclineMsg))
                {
                    return $mappedDeclineMsg;
                }
            }
        }

        /*
         * This function used Database\Connectors\ConnectionFactory class 
         */
        private function createConnection() {
            try
            {
                if (!extension_loaded('pdo_sqlite')) {
                    throw new Exception('PDO extension does not exists');
                }
                if (!file_exists($this->database)) {
                    file_put_contents($this->database, '');
                }
                if (!is_writable($this->database)) {
                    throw new Exception('Check write permission of database file');
                }
                $factory    = new ConnectionFactory();
                $connection = $factory->make(array(
                    'driver'   => 'sqlite',
                    'database' => $this->database,
                ));
                return $connection;
            } catch (Exception $ex) {
                throw($ex);
            }
        }

        /*
         * This function will create the table.
         */
        private function createTable() {
            try
            {                
                $sql = "CREATE TABLE IF NOT EXISTS '" . $this->table . "' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 'email' TEXT, 'max_block_time' DATETIME, 'status' BOOLEAN, 'last_decline_datetime' DATETIME)";
                $query = $this->createConnection()->query($sql);  
                
                $sqlUpsell = "CREATE TABLE IF NOT EXISTS '" . $this->tableUpsell . "' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 'email' TEXT, 'max_block_time' DATETIME, 'status' BOOLEAN, 'last_decline_datetime' DATETIME, 'ip_address' TEXT, 'previous_card' TEXT)";
                $queryUpsell = $this->createConnection()->query($sqlUpsell); 

                $sqlLocal = "CREATE TABLE IF NOT EXISTS '" . $this->localTable . "' "
                        . "("
                        . "'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
                        . "'email' TEXT, "
                        . "'max_block_time' DATETIME, "
                        . "'status' BOOLEAN, "
                        . "'last_order_datetime' DATETIME, "
                        . "'ip_address' TEXT, "
                        . "'previous_card' TEXT"
                        . ")";
                $this->createConnection()->query($sqlLocal); 
                
                $checkColSql = "PRAGMA table_info('" . $this->table . "')";
                $cols = $this->createConnection()->fetchAll($checkColSql);
                $colsCount = count($cols);
                
            if($colsCount < 7) {
                $alterSql = "DROP TABLE IF EXISTS '" . $this->table . "' ";
                $this->createConnection()->query($alterSql);
                
                $sql = "CREATE TABLE '" . $this->table . "' "
                        . "("
                        . "'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
                        . "'email' TEXT, "
                        . "'max_block_time' DATETIME, "
                        . "'status' BOOLEAN, "
                        . "'last_decline_datetime' DATETIME, "
                        . "'ip_address' TEXT, "
                        . "'previous_card' TEXT"
                        . ")";
                    $query = $this->createConnection()->query($sql); 
            }
                
                return true;
            } catch (Exception $ex) {
                return array(
                    'success'       => false,
                    'error_message' => $ex->getMessage(),
                );
            }
        }

        /*
         * This function will insert data into table
         */
        private function insert($data,$local=false) {
            try {
                if ($this->currentStepId > 1) 
                {
                    $this->table = $this->tableUpsell;
                }
                if($local){
                    $this->table = $this->localTable;
                }
                $this->createConnection()->table($this->table)->insert($data);
                return;
            } catch (Exception $ex) {
                throw ($ex);
            }

        }

        /*
         * Fetch data using key value equality checking
         */
        private function getEqual($key, $value){
            try {
                if ($this->currentStepId > 1) 
                {
                    $this->table = $this->tableUpsell;
                }
                $query =  $this->createConnection()->table($this->table)
                ->select('id', 'email', 'max_block_time', 'last_decline_datetime');
                $query->where($key, '=', $value);
                return $query->get();
            }
            catch(Exception $ex) {
                
            }
        }

        /*
         * Update data
         */
        private function update($id, $data) {
            try {
                if ($this->currentStepId > 1) 
                {
                    $this->table = $this->tableUpsell;
                }
                $this->createConnection()->table($this->table)
                    ->where('id', '=', $id)
                    ->update($data);
                return;
            } catch (Exception $ex) {
                throw ($ex);
            }
        }

        private function orderDecline() {

            
            if($this->config['enable_order_decline_limit']) {
                
                $allowedMethod = array('newOrderWithProspect', 'newOrder', 'newOrderCardOnFile', 'importUpsell', 'newOrderCardOnFileWithCvv');
                $method = CrmPayload::get('meta.crmMethod');
                $email = CrmPayload::get('email');

                if (!in_array($method, $allowedMethod)) {
                    return;
                }

                if ($this->currentStepId == 1) {
                    $creditCardNumber = Request::form()->get('creditCardNumber');
                }
                else{
                    $creditCardNumber = Session::get('customer.cardNumber');
                }
   
                if(!strncmp($this->config['order_decline_type'], 'Session', strlen($this->config['order_decline_type']))) {
                    // Session based order decline
                    $this->sesseionBasedOrderDecline($creditCardNumber);
                }
                else {
                    // Sqlite based order decline
                    $this->sqliteBasedOrderDecline($email, $creditCardNumber);
                }
                
                $forceGatewayId = !empty(Session::get(sprintf('extensions.VisitorBlocker.GatewayId.%s', $this->currentStepId))) ?
                Session::get(sprintf('extensions.VisitorBlocker.GatewayId.%s', $this->currentStepId)) : '';
                
                if(!empty($forceGatewayId)) {
                    CrmPayload::set('forceGatewayId', $forceGatewayId);
                    $crmType = Session::get('crmType');
                    if ($crmType == 'limelight' || $crmType == 'limelightv2') {
                        CrmPayload::set('preserveGateway', 1);
                    }
                }
            }
        }

        private function sesseionBasedOrderDecline($creditCardNumber) {
            
            if($this->currentStepId == 1) {
                $orderDeclineLimit = $this->config['order_decline_limit'];
            }
            
            $orderDeclineLimitUpsell = $this->config['order_decline_limit_upsell'];
            if($this->currentStepId > 1 && !empty($orderDeclineLimitUpsell)) {
                $orderDeclineLimit = $orderDeclineLimitUpsell;
            }
            
            if (Session::get('extensions.UserBlock.count_' . $this->currentStepId) >= $orderDeclineLimit && Session::get('extensions.UserBlock.block_time') > strtotime(date("Y-m-d H:i:s"))) {
                try{
                    if(Provider::checkExtensions('DataCapture')) {
                        $enableCaptureDecline = Config::extensionsConfig('DataCapture.enable_capture_for_decline');
                        if($enableCaptureDecline) {
                            $tableName = Config::extensionsConfig('DataCapture.local_data_table');
                            $connection = Helper::getDatabaseConnection();
                            $selectLastData = $connection->table($tableName)
                                ->where('email', '=', CrmPayload::get('email'))
                                ->orderBy('id', 'DESC')
                                ->limit(1)
                                ->get();
                            $deleteData = $connection->table($tableName)
                                ->where('id', '=', $selectLastData[0]['id'])
                                ->delete();
                        }
                    }
                } catch (Exception $ex) {

                }
                Response::send(array(
                    'success' => false,
                    'errors' => array(
                        'usererror' => !empty($this->config['order_decline_message']) ? $this->config['order_decline_message'] : 'Please try again later'
                    )
                ));
            }

            $userBlockCount = Session::get('extensions.UserBlock.count_' . $this->currentStepId);
            $userPreviousCard = Session::get('extensions.UserBlock.previous_card');

            // Card based checking.
            if ( empty($userBlockCount) && (empty($userPreviousCard) || Session::get('extensions.UserBlock.previous_card') != $creditCardNumber) ) {
                Session::set('extensions.UserBlock.count_' . $this->currentStepId, 1);
                Session::set('extensions.UserBlock.previous_card', $creditCardNumber);
                Session::set('extensions.UserBlock.block_time', date("Y-m-d H:i:s"));
            }
            elseif ( Session::get('extensions.UserBlock.previous_card') == $creditCardNumber ){
                Session::set('extensions.UserBlock.count_' . $this->currentStepId, $userBlockCount + 1);
            }
            elseif ( $this->currentStepId > 1 ) {
                Session::set('extensions.UserBlock.count_' . $this->currentStepId, $userBlockCount + 1);
            }
        }

        private function sqliteBasedOrderDecline($customerEmail, $creditCardNumber) {
            $creditCardNumber = $this->encryptData($creditCardNumber,'md5');
            $list = $this->getDbInfo($customerEmail, $creditCardNumber);
            
            if($this->currentStepId == 1) {
                $orderDeclineLimit = $this->config['order_decline_limit'];
            }
            
            $orderDeclineLimitUpsell = $this->config['order_decline_limit_upsell'];
            if($this->currentStepId > 1 && !empty($orderDeclineLimitUpsell)) {
                $orderDeclineLimit = $orderDeclineLimitUpsell;
            }
            
            if(!empty($list)) {
                if (
                        current($list)['max_block_time'] >= $orderDeclineLimit && 
                        strtotime(current($list)['last_decline_datetime']) > strtotime(date("Y-m-d H:i:s"))
                ) {
                    try{
                        if(Provider::checkExtensions('DataCapture')) {
                            $enableCaptureDecline = Config::extensionsConfig('DataCapture.enable_capture_for_decline');
                            if($enableCaptureDecline) {
                                $tableName = Config::extensionsConfig('DataCapture.local_data_table');
                                $connection = Helper::getDatabaseConnection();
                                $selectLastData = $connection->table($tableName)
                                    ->where('email', '=', CrmPayload::get('email'))
                                    ->orderBy('id', 'DESC')
                                    ->limit(1)
                                    ->get();
                                $deleteData = $connection->table($tableName)
                                    ->where('id', '=', $selectLastData[0]['id'])
                                    ->delete();
                            }
                        }
                    } catch (Exception $ex) {

                    }
                    Response::send(array(
                        'success' => false,
                        'errors' => array(
                            'usererror' => !empty($this->config['order_decline_message']) ? $this->config['order_decline_message'] : 'Please try again later'
                        )
                    ));
                }
                elseif (strtotime(current($list)['last_decline_datetime']) < strtotime(date("Y-m-d H:i:s"))){
                  
                    //update if old time expired
                    $blockTime = $this->config['default_block_time'];
                    $time = new DateTime();
                    $time->add(new DateInterval('PT0H' . $blockTime . 'M0S'));

                    $tempId = current($list)['id'];
                    $this->update($tempId, array(
                        'max_block_time' => 0,
                        'last_decline_datetime' => $time->format("Y-m-d H:i:s"),
                    ));

                }
            }
        }

        public function checkTimeBasedDecline() {

            $enableTimeBasedBlock = $this->config['enable_block_user_repeat_order'];

            if (
                (Request::attributes()->get('action') != 'prospect' && 
                    Request::attributes()->get('action') != 'checkout' && 
                    Request::attributes()->get('action') != 'downsell') 
                    || 
                    !$enableTimeBasedBlock) {
                return;
            }
           
            $blockType = $this->config['time_based_block_type'];
            if (!$enableTimeBasedBlock) {
                return;
            }
            
            $blockMsg = $this->config['time_based_block_message'];
            $redirectUrl = $this->config['redirect_url'];
            
            $params = Request::form()->all();
            $params['blockTime'] = $this->config['block_time'];
            
            $data = $this->getOrdersForCrm(Session::get('crmType'), $params, $blockType);
            
            if($data)
            {
                if(!empty($redirectUrl))
                {
                    Response::send(array(
                        'success'          => false,
                        'errors'           => array('crmError' => 'Redirect!'),
                        'Redirect'         => $redirectUrl,
                    ));
                }
                else
                {
                    Response::send(array(
                        'success' => false,
                        'errors' => array(
                            'binerror' => !empty($blockMsg) ? $blockMsg : $this->declineText
                        )
                    ));
                }
            }
        }

        public function getOrdersForCrm($crmType, $params, $blockType) {

            if(!strcmp($crmType, 'konnektive')) {

                date_default_timezone_set('America/New_York');
                
                
                $this->apiEndPoint = Registry::system('systemConstants.KONNEKTIVE_API_BASE_URL') . "/transactions/query/";
                $this->curlPostData['startDate'] = date('m/d/Y', strtotime('-' . $params['blockTime'] . ' Hours'));
                $this->curlPostData['endDate'] = date('m/d/Y');
                $start = date('H:i');
                $num_hours = $params['blockTime']; //some float
                $hours = floor($num_hours);
                $mins = round(($num_hours - $hours) * 60);
                $this->curlPostData['startTime'] = date('H:i',strtotime('-'. $hours . ' hour'.'-'.$mins .'minutes',strtotime($start)));
                $this->curlPostData['orderStatus'] = 'COMPLETE';

                $this->curlPostData['responseType'] = 'SUCCESS';
                
                $crmInfo = $this->configuration->getCrm();
                $this->curlPostData['loginId'] = $crmInfo['username'];
                $this->curlPostData['password'] = $crmInfo['password'];
                
                if (!empty($this->config['time_based_block_type']))
                {
                    if (
                            in_array(strtoupper('ipAddress'), $this->config['time_based_block_type']) 
                            && !$this->getInWhitelistDetails(array('whitelist_ip' => $this->ip))
                            && in_array(Request::attributes()->get('action'), ['prospect', 'downsell'])
                        )
                    {

                        
                        $this->apiEndPoint = Registry::system('systemConstants.KONNEKTIVE_API_BASE_URL') . "/order/query/";
                        $this->curlPostData['ipAddress'] = Request::getClientIp();
                        
                        
                        $this->curlResponse = Http::post($this->apiEndPoint, http_build_query($this->curlPostData));
                        $data = json_decode($this->curlResponse, true);
                        
                        
                        if (!empty($data['result']) && $data['result'] == 'SUCCESS')
                        {

                            return true;
                           
                        }
                        else{
                            unset($this->curlPostData['ipAddress']);
                        }
                    }

                    if (
                            in_array(strtoupper('email'), $this->config['time_based_block_type']) 
                            && !$this->getInWhitelistDetails(array('whitelist_email' => $params['email']))
                            && in_array(Request::attributes()->get('action'), ['prospect', 'downsell'])
                        )
                    {
                        $this->curlPostData['emailAddress'] = $params['email'];
                        
                        $this->curlResponse = Http::post($this->apiEndPoint, http_build_query($this->curlPostData));
                        $data = json_decode($this->curlResponse, true);
                        
                        if (!empty($data['result']) && $data['result'] == 'SUCCESS')
                        {
                            return true;
                        }
                    }

                    if (in_array(strtoupper('CREDITCARD'), $this->config['time_based_block_type']) && !$this->getInWhitelistDetails(
                                array('whitelist_card' => $params['creditCardNumber']
                                )
                        )
                        && (Request::attributes()->get('action') == 'downsell' || Request::attributes()->get('action') == 'checkout')
                        )
                    {
                        $creditCardNumber = $params['creditCardNumber'];
                        $first_6_cc = substr($creditCardNumber, 0, 6);
                        $last_4_cc = substr($creditCardNumber, -4);
                        $this->curlPostData['cardBin'] = $first_6_cc;
                        $this->curlPostData['cardLast4'] = $last_4_cc;

                        $this->curlResponse = Http::post($this->apiEndPoint, http_build_query($this->curlPostData));
                        $data = json_decode($this->curlResponse, true);
                        if (!empty($data['result']) && $data['result'] == 'SUCCESS')
                        {
                            return true;
                        }
                    }

                    

                    // Domain checking
                    $domain = explode('@', $params['email'])[1];
                    if (
                            in_array('DOMAIN', $this->config['time_based_block_type']) 
                            && ($this->currentPageType == 'leadPage' || Request::attributes()->get('action') == 'downsell') && !$this->getInWhitelistDetails(
                            array('whitelist_domain' => $domain
                            )
                    ))
                    {
                        $this->apiEndPoint = Registry::system('systemConstants.KONNEKTIVE_API_BASE_URL') . "/order/query/";
                        $this->curlPostData['emailAddress'] = sprintf('%s', $domain);
                        $this->curlResponse = Http::post($this->apiEndPoint, http_build_query($this->curlPostData));
                        $data = json_decode($this->curlResponse, true);
                        
                        if (!empty($data['result']) && $data['result'] == 'SUCCESS')
                        {
                            return true;
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            else if(!strcmp($crmType, 'limelight') || !strcmp($crmType, 'limelightv2')) {
                date_default_timezone_set('America/New_York');
                $this->curlPostData['method'] = 'order_find';
                $this->curlPostData['campaign_id'] = 'all';
                $this->curlPostData['start_date'] = date('m/d/Y', strtotime('-' . $params['blockTime'] . ' Hours'));
                $this->curlPostData['end_date'] = date('m/d/Y');
                $this->curlPostData['search_type'] = 'all';
                $this->curlPostData['return_type'] = 'order_view';
                $start = date('H:i');
                $num_hours = $params['blockTime']; //some float
                $hours = floor($num_hours);
                $mins = round(($num_hours - $hours) * 60);
                $this->curlPostData['start_time'] = date('H:i:s',strtotime('-'. $hours . ' hour'.'-'.$mins .'minutes',strtotime($start)));
                $this->curlPostData['end_time'] = date('H:i:s');
               
                $crmInfo = $this->configuration->getCrm();

                $this->curlPostData['username'] = $crmInfo['username'];
                $this->curlPostData['password'] = $crmInfo['password'];
                $url = $crmInfo['endpoint'] . "/admin/membership.php";
                
                if (is_array($blockType))
                {
                    if (in_array(strtoupper('ipAddress'), $blockType) && !$this->getInWhitelistDetails(
                            array('whitelist_ip' => $this->ip
                            )
                    ))
                    {
                        $this->curlPostData['criteria'] = "'ip_address=" . Request::getClientIp() . "'";
                        $this->curlResponse = Http::post($url, http_build_query($this->curlPostData));
                        parse_str($this->curlResponse, $result);
                        if (!empty($result['response_code']) && $result['response_code'] == '100')
                        {
                            return true;
                        }
                    }
                    
                    if (in_array('CREDITCARD', $blockType) && !$this->getInWhitelistDetails(
                            array('whitelist_card' => $params['creditCardNumber']
                            )
                    )
                      && (Request::attributes()->get('action') == 'downsell' || Request::attributes()->get('action') == 'checkout')      
                    )
                    {
                        $creditCardNumber = $params['creditCardNumber'];
                        $first_6_cc = substr($creditCardNumber, 0, 6);
                        $last_4_cc = substr($creditCardNumber, -4);
                        $criteria = "'first_6_cc=" . $first_6_cc . ",last_4_cc=" . $last_4_cc . ",approved,shipped'";
                        $this->curlPostData['criteria'] = $criteria;
                        $this->curlResponse = Http::post($url, http_build_query($this->curlPostData));
                        parse_str($this->curlResponse, $result);
                        if (!empty($result['response_code']) && $result['response_code'] == '100')
                        {
                            return true;
                        }
                    }

                    if (in_array('EMAIL', $blockType) && $this->currentPageType == 'leadPage' && !$this->getInWhitelistDetails(
                            array('whitelist_email' => $params['email']
                            )
                    ))
                    {
                        $criteria = "'email=" . $params['email'] . ",approved,shipped'";
                        $this->curlPostData['criteria'] = $criteria;
                        //print_r($this->curlPostData);
                        $this->curlResponse = Http::post($url, http_build_query($this->curlPostData));
                        //print_r($this->curlResponse);
                        //die('from extension');
                        parse_str($this->curlResponse, $result);
                        if (!empty($result['response_code']) && $result['response_code'] == '100')
                        {
                            return true;
                        }
                    }
                    else if (in_array('EMAIL', $blockType) && Request::attributes()->get('action') != 'downsell' &&
                        !$this->getInWhitelistDetails(
                                array('whitelist_email' => $params['email']
                                )
                        ))
                    {
                        $criteria = "'email=" . $params['email'] . ",approved,shipped'";
                        $this->curlPostData['criteria'] = $criteria;
                        $this->curlResponse = Http::post($url, http_build_query($this->curlPostData));
                        parse_str($this->curlResponse, $result);
                        if (!empty($result['response_code']) && $result['response_code'] == '100')
                        {
                            return true;
                        }
                    }
                    else
                    {
                        return false;
                    }

                    // Domain checking
                    $domain = explode('@', $params['email'])[1];
                    if (in_array('DOMAIN', $blockType) && $this->currentPageType == 'leadPage' && !$this->getInWhitelistDetails(
                            array('whitelist_domain' => $domain
                            )
                    ))
                    {

                        $criteria = "'email=*@" . $domain . ",approved,shipped'";
                        $this->curlPostData['criteria'] = $criteria;
                        $this->curlResponse = Http::post($url, http_build_query($this->curlPostData));
                        parse_str($this->curlResponse, $result);
                        if (!empty($result['response_code']) && $result['response_code'] == '100')
                        {
                            return true;
                        }
                    }
                    else if (in_array('DOMAIN', $blockType) && Request::attributes()->get('action') != 'downsell' &&
                        !$this->getInWhitelistDetails(
                                array('whitelist_email' => $domain
                                )
                        ))
                    {
                        $criteria = "'email=*@" . $params['email'] . ",approved,shipped'";
                        $this->curlPostData['criteria'] = $criteria;
                        $this->curlResponse = Http::post($url, http_build_query($this->curlPostData));
                        parse_str($this->curlResponse, $result);
                        if (!empty($result['response_code']) && $result['response_code'] == '100')
                        {
                            return true;
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
                else if (
                            !$this->getInWhitelistDetails(
                                array('whitelist_email' => $params['email']
                            )
                        )
                    )
                {
                    $criteria = "'email=" . $params['email'] . ",approved,shipped'";
                    $this->curlPostData['criteria'] = $criteria;
                    $this->curlResponse = Http::post($url, http_build_query($this->curlPostData));
                    parse_str($this->curlResponse, $result);
                    if (!empty($result['response_code']) && $result['response_code'] == '100')
                    {
                        return true;
                    }
                }
            }

            
            
            return false;
        }

        protected function getInWhitelistDetails($filterKeys = array()) {

            if (empty($filterKeys))
            {
                    return false;
            }
            $whiteList = array();
            $whiteList['whitelist_ip'] = preg_split("/\\r\\n|\\r|\\n/", $this->config['ip_whitelists']);
            $whiteList['whitelist_email'] = preg_split("/\\r\\n|\\r|\\n/", $this->config['email_to_whitelists']);
            $whiteList['whitelist_card'] = preg_split("/\\r\\n|\\r|\\n/", $this->config['credit_card_whitelists']);
            $whiteList['whitelist_domain'] = preg_split("/\\r\\n|\\r|\\n/", $this->config['domain_to_whitelists']);

            foreach (array_keys($whiteList) as $key => $value)
            {
                    if (empty($whiteList[$value][0]))
                    {
                            $whiteList[$value] = false;
                    }
            }
            foreach (array_keys($filterKeys) as $value)
            {
                    if (!empty($whiteList[$value]) && in_array($filterKeys[$value], $whiteList[$value]))
                    {
                            return true;
                    }
            }

            return false;
        }

        public function filterhostname() {
            
            if(!empty($this->config['enable_filter_based_host_name']) && !empty($this->config['block_host_names'])) {
                if (empty($this->checkBlockTld($this->config['block_host_names']))){

                    if(!strcmp($this->config['host_name_action_type'], 'redirect', strlen('redirect'))) {
                        $url = $this->config['host_name_redirect_url'];
                    }
                    else if(!strcmp($this->config['host_name_action_type'], 'auto', strlen('redirect')) && empty($this->config['host_name_redirect_url'])) {
                        $url = "https://www.google.com";
                    }

                    echo "<script>window.location.href='" . $url . "'</script>";
                    exit();
                }
            }
        }

        private function checkBlockTld($blockTlds) {

            $this->clientHost = gethostbyaddr($this->ip);
            $blockTldsAll = preg_split("/\\r\\n|\\r|\\n/", $blockTlds);
            $blockRegx = '/(';
            foreach ($blockTldsAll as $value)
            {
                $value = trim($value, '.');
                $blockRegx .= '\.' . $value . '|';
            }
            $blockRegx = rtrim($blockRegx, '|');
            $blockRegx .= ')/mi';
            if (preg_match_all($blockRegx, $this->clientHost))
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        public function injectScript() {

            if ($this->currentPageType == "leadPage")
            {
                $urlReferrerList = preg_split("/\\r\\n|\\r|\\n/", $this->config['url_referrer_block']);
                $urlreferrer = array();
                if (empty($urlReferrerList))
                {
                    return true;
                }
                foreach ($urlReferrerList as $value)
                {
                    $referrer = explode('=', $value);
                    $urlreferrer[$referrer[0]] = $referrer[1];
                }

                if(!strcmp($this->config['url_referrer_block_action_type'], 'redirect', strlen('redirect'))) {
                    $url = $this->config['url_referrer_block_redirect_url'];
                }
                else if(!strcmp($this->config['url_referrer_block_action_type'], 'auto', strlen('redirect')) && empty($this->config['url_referrer_block_redirect_url'])) {
                    $url = "https://www.google.com";
                }


                $script = '<script>'
                        . 'var reqUrlReferrer = ' . json_encode($urlreferrer) . ';'
                        . 'var urlReferrerRouteURL = "' . $url
                        . '";</script><script src="extensions/TrafficFilter/js/urlreferrer.js"></script>';
                echo $script;
            }
        }

        public function countryBlocking() {

            if(empty($this->config['enable_country_blacklist']) || empty($this->config['block_country_list'])) {
                return;
            }

            if(Request::attributes()->get('action') != 'downsell' && Request::attributes()->get('action') != 'prospect') {
                return;
            }

            $params = Request::form()->all();
            $blockCountryLst = explode(',', $this->config['block_country_list']);

            if(in_array($params['shippingCountry'], $blockCountryLst)) {

                if($this->config['country_blocking_method'] == 'auto') {
                    Response::send(array(
                        'success' => false,
                        'errors' => array(
                            'usererror' => 'The country you have selected is not allowed.'
                        )
                    ));
                }
                else if(!empty($this->config['country_blocking_redirect_url'])) {
                    $url = $this->config['country_blocking_redirect_url'];
                    $form = <<<HTML
                    <html>
                    <head></head>
                    <body>
                        <script>window.location.href="$url"</script>
                    </body>
                    </html>
HTML;

                    Response::send(
                        array(
                            'success' => true,
                            'errors'  => array(),
                            'html'    => $form,
                            'is_html' => true,
                        )
                    );
                }
            }
        }

        public function localBlacklist() {

            if(empty($this->config['enable_blacklist'])) {
                return;
            }

            $params = Request::form()->all();

            $binDeclineText = 'Invalid credit card, Please try a different card.';
            $emailDeclineText = 'Invalid email, Please try a different email.';
            $ipDeclineText = 'Invalid IP address, Please try with diffrent IP address';
            $cityDeclineText = 'Please try with diffrent City';
            $zipDeclineText = 'Invalid zip, Please try a different zip.';

            if(!empty($this->config['ip_address_blacklist_list'])) {
                $iplist = preg_split("/\\r\\n|\\r|\\n/", $this->config['ip_address_blacklist_list']);

                if(in_array($this->ip, $iplist)) {
                    Response::send(array(
                        'success' => false,
                        'errors' => array(
                            'usererror' => !empty($this->config['ip_blacklist_msg']) ? $this->config['ip_blacklist_msg'] : $ipDeclineText
                        )
                    ));
                }
            }

            if(!empty($this->config['email_to_blacklists'])) {

                $isBlacklist = false;

                $emailList = preg_split("/\\r\\n|\\r|\\n/", $this->config['email_to_blacklists']);

                foreach ($emailList as $email)
                {
                    if (preg_match("/^" . $email . "$/", $params['email']))
                    {
                        $isBlacklist = true;
                    }

                    $email_domain = explode('@', $params['email']);
                    if (preg_match("/^" . $email . "$/", $email_domain[1]))
                    {
                        $isBlacklist = true;
                    }

                    $emailDomainExt = explode('.', $params['email']);
                    $emailDomainExt = end($emailDomainExt);
                    if ($emailDomainExt === $email)
                    {
                        $isBlacklist = true;
                    }
                }

                if($isBlacklist) 
                {
                    Response::send(array(
                        'success' => false,
                        'errors' => array(
                            'usererror' => !empty($this->config['email_blacklist_msg']) ? $this->config['email_blacklist_msg'] : $emailDeclineText
                        )
                    ));
                } 
            }

            if(!empty($this->config['city_blacklist_list'])) {
                $citylist = preg_split("/\\r\\n|\\r|\\n/", $this->config['city_blacklist_list']);
                $citylist = array_map('strtolower', $citylist);

                if(in_array($this->city, $citylist)) {
                    Response::send(array(
                        'success' => false,
                        'errors' => array(
                            'usererror' => !empty($this->config['city_blacklist_msg']) ? $this->config['city_blacklist_msg'] : $cityDeclineText
                        )
                    ));
                }
            }

            if(!empty($this->config['zip_blacklist_list'])) {
                $ziplist = preg_split("/\\r\\n|\\r|\\n/", $this->config['zip_blacklist_list']);

                if(in_array($this->zip, $ziplist)) {
                    Response::send(array(
                        'success' => false,
                        'errors' => array(
                            'usererror' => !empty($this->config['zip_blacklist_msg']) ? $this->config['zip_blacklist_msg'] : $zipDeclineText
                        )
                    ));
                }
            }

            if(Request::attributes()->get('action') == 'downsell' || Request::attributes()->get('action') == 'checkout') {
                // check the credit card here
                if(!empty($this->config['credit_card_blacklists'])) {
                    
                    $cardList = preg_split("/\\r\\n|\\r|\\n/", $this->config['credit_card_blacklists']);
                    if(in_array($params['creditCardNumber'], $cardList)) {
                        Response::send(array(
                            'success' => false,
                            'errors' => array(
                                'usererror' => !empty($this->config['cc_blacklist_msg']) ? $this->config['cc_blacklist_msg'] : $binDeclineText
                            )
                        ));
                    }                
                }
            }
        }
        
        public function getGatewayId()
        {
            $enableOrderDeclineLimit = $this->config['enable_order_decline_limit'];
            if (!$enableOrderDeclineLimit)
            {
                return;
            }
            $crmResponse = CrmResponse::all();
            
            if($crmResponse['success']) {
                return;
            }
            
            if(
                !empty($crmResponse['errors']['crmError']) &&
                preg_match("/Prepaid.+Not Accepted|Prepaid.+not allowed/i", $crmResponse['errors']['crmError'])
            ) {
                return;
            }
            
            $forceGatewayRetry = !empty($this->config['force_gateway_decline']) ? $this->config['force_gateway_decline'] : '';
            $allowedMethod = array('newOrderWithProspect', 'newOrder', 'newOrderCardOnFile', 'importUpsell');
            $method = CrmPayload::get('meta.crmMethod');
            
            if($forceGatewayRetry && in_array($method, $allowedMethod)) {
                $crmType = Session::get('crmType');
                if($crmType == 'vrio' && !empty(CrmResponse::get('gatewayId'))) {
                    $gatewayId = CrmResponse::get('gatewayId');
                } else {
                    $gatewayId = $this->orderView($crmResponse['declineOrderId']);
                }
            }
            
            $specificGatewayForce = $this->config['specific_force_gateway_decline'];
            $forceGatewayIDs = array();
            if($specificGatewayForce) {
                $gatewaySettings = $this->config['gateway_settings'];
                foreach($gatewaySettings as $key => $value) {
                    if($value['step_id'] == $this->currentStepId) {
                        $forceGatewayIDs = explode(",", $value['gateway_id']);
                        break;
                    }
                }
                $forceGaewayIDRandKey = array_rand($forceGatewayIDs);
                if(!empty($forceGatewayIDs[$forceGaewayIDRandKey])){
                    $gatewayId = $forceGatewayIDs[$forceGaewayIDRandKey];
                }
            }
            
            if(!empty($gatewayId))
            {
                Session::set(sprintf('extensions.VisitorBlocker.GatewayId.%s', $this->currentStepId), $gatewayId);
            }
            
        }
        
        private function orderView($orderID)
        {
            $result = array();
            $configId = Session::get('steps.current.configId');

            $this->curlPostData['order_id'] = $orderID;
            $this->curlPostData['method'] = 'order_view';
            $this->configuration = new Configuration($configId);

            $crmInfo = $this->configuration->getCrm();

            $this->curlPostData['username'] = $crmInfo['username'];
            $this->curlPostData['password'] = $crmInfo['password'];

            $url = $crmInfo['endpoint'] . "/admin/membership.php";
            $this->curlResponse = Http::post($url, http_build_query($this->curlPostData));

            parse_str($this->curlResponse, $result);
            if($result['response_code'] == 100) {
                $gatewayId = $result['gateway_id'];
            }
            return $gatewayId;
        }
        
    public function checkAddressBlock($downsellBillingCheck = false)
    {

        if (
                ($this->currentPageType != "leadPage" ||
                $this->currentPageType != "checkoutPage") &&
                empty($this->config['enable_addressblock'])
            )
        {
            return;
        }


        $address = CrmPayload::get('shippingAddress1') . " " .
                CrmPayload::get('shippingCity') .
                CrmPayload::get('shippingZip') . " " .
                " " . CrmPayload::get('shippingState');

        if (Request::attributes()->get('action') == "checkout" &&
                strtolower(CrmPayload::get('billingSameAsShipping')) == "yes" &&
                Request::attributes()->get('action') != "downsell")
        {
            return;
        }

        if ((Request::attributes()->get('action') == "checkout" || $downsellBillingCheck) &&
                strtolower(CrmPayload::get('billingSameAsShipping')) == "no")
        {

            $address = CrmPayload::get('billingAddress1') . " " .
                    CrmPayload::get('billingCity') .
                    CrmPayload::get('billingZip') . " " .
                    " " . CrmPayload::get('billingState');
        }

        try
        {
            $status = $this->validateAddress($address);
            if (empty($status))
            {
                throw new Exception("Something went wrong!");
            }

            if (empty($status['success']))
            {
                $errorMessage = empty($status['errors']) ? "Something went wrong" :
                        $status['errors'];
                Response::send(array(
                    'success' => false,
                    'errors' => array('err' => $errorMessage)
                ));
                return;
            }
            if (!$downsellBillingCheck &&
                    Request::attributes()->get('action') == "downsell" &&
                    strtolower(CrmPayload::get('billingSameAsShipping')) == "no")
            {
                $this->checkAddressBlock(true);
            }
            return;
        }
        catch (Exception $ex)
        {
            echo $ex->getMessage();
            die;
            Response::send(array(
                'success' => false,
                'errors' => array('err' => "Something went wrong!"
            )));
            return;
        }
    }
    
    private function validateAddress($address) { 
        $endPoint = "https://maps.googleapis.com/maps/api/geocode/json";

        $url = $endPoint."?".http_build_query(
                array(
                    'address' => urldecode($address),
                    'key' => $this->config['googlePlaceAPIKey']
                ));
        $response = Http::get($url);
        if (!empty($response['curlError'])) {
            return  array(
                'success' => false,
                'errors' => "Something went wrong"
            );
        }

        $response = json_decode($response,true); 
        if(!empty($response['error_message'])){
            return  array(
                'success' => false,
                'errors' => $response['error_message']
            );
        }

        $response = $response['results'][0]['geometry'];

        if(empty($response['location']['lat']) || 
                empty($response['location']['lng'])){
            return  array(
             'success' => true
             );
        }
        $isBlockThisAddress = false;
        foreach ($this->config['addressblock'] as $key => $value) {
            if($address == $value['addressToBlock']){
                $isBlockThisAddress = true;
                break;
            }
            if($response['location']['lat'] == $value['lat'] && 
                    $response['location']['lng'] == $value['lng']){
                $isBlockThisAddress = true;
                break;
            }
        }

        if($isBlockThisAddress){
            return  array(
                'success' => false,
                'errors' => empty($this->config['addressBlockErrorMsg']) ? "Try with another Address."
                    : $this->config['addressBlockErrorMsg']
                );
        }

        return  array(
            'success' => true
        );

    }

    public function isOldFrameworkVersion()
    {
        if(!empty(\Application\Registry::system('systemConstants.FRAMEWORK_V5')))
        {
            return false;
        }
        $currentVersion = \Application\Registry::system('systemConstants.version');
        $changedVersion = 10;

        $parsedCurrentVersion = explode('.', $currentVersion);
        if($changedVersion > $parsedCurrentVersion[1])
        {
            return true;
        }
        return false;
    }
    
    
    public function save() {
        //Strict version check for fallback major update
        if($this->isOldFrameworkVersion())
        {
            throw new Exception("Please update the framework to make it compatible with this extension version and then try to resave this. !!");
        }
        $requestData = Request::form()->all();
        Request::form()->remove('addressblock');
        if(empty($requestData['enable_addressblock'])){
            return true;
        }
        $geoCodes = array();
        $endPoint = "https://maps.googleapis.com/maps/api/geocode/json";
        $data = array();
        foreach ($requestData['addressblock'] as $key => $value) {
            $url = $endPoint."?".http_build_query(
                array(
                    'address' => urldecode($value['addressToBlock']),
                    'key' => $requestData['googlePlaceAPIKey']
                ));
            $response = Http::get($url);
            if (!empty($response['curlError'])) {
                  throw new Exception("Something went wrong");
            }
            $response = json_decode($response,true); 
            if(!empty($response['error_message'])){
                throw new Exception($response['error_message']);
            }

            $response = $response['results'][0]['geometry'];
            if(empty($response['location']['lat']) || empty($response['location']['lng'])){
                throw new Exception("No lat long found for ".$value['addressToBlock']);
            }
            $data[$key]['addressToBlock'] = $value['addressToBlock'];
            $data[$key]['lat'] = $response['location']['lat'];
            $data[$key]['lng'] = $response['location']['lng'];
        }

        Request::form()->set('addressblock',$data);
        return true;
    }
    
    public function getDbInfo($email, $creditCardNumber)
    {
        if(!empty($this->config['order_block_type']) && in_array('ccip', $this->config['order_block_type']))
        {
            if ($this->currentStepId > 1) {
                $this->table = $this->tableUpsell;
            }
            $query =  $this->createConnection()->table($this->table)
                        ->select('id', 'email', 'max_block_time', 'last_decline_datetime');
            $query->where('ip_address', '=' , Request::getClientIp());
            $query->where('previous_card', '=' , $creditCardNumber);
            $list = $query->get();
            if (!empty($list)) {
                return $list;
            }
            
        }
        if(!empty($this->config['order_block_type']) && in_array('cc', $this->config['order_block_type'] ))
        {
            $list = $this->getEqual('previous_card', $creditCardNumber);
            if (!empty($list)) {
                return $list;
            }
        }
        if(!empty($this->config['order_block_type']) && in_array('ipaddress', $this->config['order_block_type']))
        {

            $list = $this->getEqual('ip_address', Request::getClientIp());
            if (!empty($list)) {
                return $list;
            }
        }
        if(!empty($this->config['order_block_type']) && in_array('email', $this->config['order_block_type'])){
            $list = $this->getEqual('email', $email);
            if (!empty($list)) {
                return $list;
            }
        }
        
        return $list = !empty($list) ? $list : false;
    }

    public function globalShield() {

        if(empty($this->config['enable_global_shield'])) {
            return;
        }

        $sourcePath = STORAGE_DIR . DS . 'shields.data.json';

        if(!file_exists($sourcePath))
        {
            return;
        }

        $params = Request::form()->all();

        $binDeclineText = 'Invalid credit card, Please try a different card.';
        $emailDeclineText = 'Invalid email, Please try a different email.';
        $ipDeclineText = 'Invalid IP address, Please try with diffrent IP address';
        $phoneDeclineText = 'Invalid Phone number, Please try with diffrent Phone number';

        $allTokens = file_get_contents($sourcePath);
        if(empty($allTokens))
        {
            return;
        }
        $shieldData = json_decode($allTokens, true);
        
        if(!empty($shieldData['ip'])) {
            $iplist = $shieldData['ip'];
            if(in_array($this->ip, $iplist)) {
                Response::send(array(
                    'success' => false,
                    'errors' => array(
                        'usererror' => !empty($this->config['ip_blacklist_msg']) ? $this->config['ip_blacklist_msg'] : $ipDeclineText
                    )
                ));
            }
        }

        if(!empty($shieldData['email'])) {
            $isBlacklist = false;
            $emailList = $shieldData['email'];
            if(in_array($params['email'], $emailList)) {
                Response::send(array(
                    'success' => false,
                    'errors' => array(
                        'usererror' => !empty($this->config['ip_blacklist_msg']) ? $this->config['ip_blacklist_msg'] : $emailDeclineText
                    )
                ));
            }
        }

        if(!empty($shieldData['phone'])) {
            $isBlacklist = false;
            $phonelist = $shieldData['phone'];
            if(in_array($params['phone'], $phonelist)) {
                Response::send(array(
                    'success' => false,
                    'errors' => array(
                        'usererror' => !empty($this->config['email_blacklist_msg']) ? $this->config['email_blacklist_msg'] : $phoneDeclineText
                    )
                ));
            }
        }

        if(Request::attributes()->get('action') == 'downsell' || Request::attributes()->get('action') == 'checkout') {
            if(!empty($shieldData['cc'])) {
                $cardList = $shieldData['cc'];
                if(in_array($params['creditCardNumber'], $cardList)) {
                    Response::send(array(
                        'success' => false,
                        'errors' => array(
                            'usererror' => !empty($this->config['cc_blacklist_msg']) ? $this->config['cc_blacklist_msg'] : $binDeclineText
                        )
                    ));
                }                
            }
        }
    }

    public function encryptData($data, $algo = '')
    {
        if(empty($algo))
        {
            $algo = "sha256";
        }

        return hash($algo, $data);
    }

    public function checkLocalRepeatOrders() {

        $enableTimeBasedBlock = $this->config['enable_block_user_repeat_order_local'];

        if (
                (
                    Request::attributes()->get('action') != 'checkout' && 
                    Request::attributes()->get('action') != 'downsell'
                ) 
                || 
                !$enableTimeBasedBlock) {
            return;
        }
       
        $blockType = $this->config['time_based_block_type_local'];
        if (!$enableTimeBasedBlock) {
            return;
        }
        
        $blockMsg = $this->config['time_based_block_message_local'];
        $redirectUrl = $this->config['redirect_url_local'];
        
        $params = Request::form()->all();
        $params['blockTime'] = $this->config['block_time_local'];
        $data = $this->checkForRepeatOrders($params, $blockType);

        if($data)
        {
            if(!empty($redirectUrl))
            {
                Response::send(array(
                    'success'          => false,
                    'errors'           => array('crmError' => 'Redirect!'),
                    'Redirect'         => $redirectUrl,
                ));
            }
            else
            {
                Response::send(array(
                    'success' => false,
                    'errors' => array(
                        'binerror' => !empty($blockMsg) ? $blockMsg : $this->declineText
                    )
                ));
            }
        }else{
            $email = Request::form()->get('email');
            $creditCardNumber = Request::form()->get('creditCardNumber');

            if(empty($creditCardNumber)) {
                $creditCardNumber = Session::get('customer.cardNumber');
            }
            
            $creditCardNumber = $this->encryptData($creditCardNumber,'md5');
            
            //insert new
            $blockTime = $this->config['block_time_local'];
            $time = new DateTime();
            $time->add(new DateInterval('PT0H' . $blockTime . 'M0S'));
            $this->insert(array(
                'email' => $email,
                'max_block_time' => 1,
                'last_order_datetime' => $time->format("Y-m-d H:i:s"),
                'ip_address' => Request::getClientIp(),
                'previous_card' => $creditCardNumber
            ), true);
            
            return;
        }
    }

    public function checkForRepeatOrders($params, $blockType){
        if (is_array($blockType))
        {
            /** Ip block */
            if (in_array(strtoupper('ipAddress'), $blockType) && !$this->getInLocalWhitelistDetails(
                array('whitelist_ip' => Request::getClientIp()
                )
            )){
                $query =  $this->createConnection()->table($this->localTable)
                    ->select('id', 'email', 'max_block_time', 'ip_address', 'last_order_datetime', 'previous_card');
                $query->where('ip_address', '=' , Request::getClientIp());
                $list = $query->get();
                
                if (!empty($list)) {
                    return $this->checkIfDateTimeIsWithinRange($list);
                }
            }
            
            /** Creditcard block */
            if (in_array('CREDITCARD', $blockType) && !$this->getInLocalWhitelistDetails(
                array('whitelist_card' => $params['creditCardNumber']
                )
            )
            && (Request::attributes()->get('action') == 'downsell' || Request::attributes()->get('action') == 'checkout')      
            ){
                $query1 =  $this->createConnection()->table($this->localTable)
                        ->select('id', 'email', 'max_block_time', 'ip_address', 'last_order_datetime', 'previous_card');
                $query1->where('previous_card', '=' , $this->encryptData($params['creditCardNumber'],'md5'));
                $list = $query1->get();
                
                if (!empty($list)) {
                    
                    return $this->checkIfDateTimeIsWithinRange($list);
                }
            }

            /** Email Block */
            if (in_array('EMAIL', $blockType) && $this->currentPageType == 'leadPage' && !$this->getInLocalWhitelistDetails(
                array('whitelist_email' => $params['email']
                )
            )){
                $query2 =  $this->createConnection()->table($this->localTable)
                    ->select('id', 'email', 'max_block_time', 'ip_address', 'last_order_datetime', 'previous_card');
                $query2->where('email', '=' , $params['email']);
                $list = $query2->get();
                
                if (!empty($list)) {
                    return $this->checkIfDateTimeIsWithinRange($list);
                }
            }
            else if (in_array('EMAIL', $blockType) && Request::attributes()->get('action') != 'downsell' &&
                !$this->getInLocalWhitelistDetails(
                        array('whitelist_email' => $params['email']
                        )
            )){
                $query3 =  $this->createConnection()->table($this->localTable)
                    ->select('id', 'email', 'max_block_time', 'ip_address', 'last_order_datetime', 'previous_card');
                $query3->where('email', '=' , $params['email']);
                $list = $query3->get();
                
                if (!empty($list)) {
                    return $this->checkIfDateTimeIsWithinRange($list);
                }
            }

            // Domain checking
            $domain = explode('@', $params['email'])[1];
            if (in_array('DOMAIN', $blockType) && $this->currentPageType == 'leadPage' && !$this->getInLocalWhitelistDetails(
                    array('whitelist_domain' => $domain
                    )
            )){
                $query4 =  $this->createConnection()->table($this->localTable)
                    ->select('id', 'email', 'max_block_time', 'ip_address', 'last_order_datetime', 'previous_card');
                $query4->where('email', 'LIKE' , '%'.$domain.'%');
                $list = $query4->get();

                if (!empty($list)) {
                    return $this->checkIfDateTimeIsWithinRange($list);
                }
            }
            else if (in_array('DOMAIN', $blockType) && Request::attributes()->get('action') != 'downsell' &&
                !$this->getInLocalWhitelistDetails(
                        array('whitelist_email' => $domain
                        )
            )){
                $query5 =  $this->createConnection()->table($this->localTable)
                    ->select('id', 'email', 'max_block_time', 'ip_address', 'last_order_datetime', 'previous_card');
                $query5->where('email', 'LIKE' , '%'.$domain.'%');
                $list = $query5->get();

                if (!empty($list)) {
                    return $this->checkIfDateTimeIsWithinRange($list);
                }
            }
        }else if (
            !$this->getInLocalWhitelistDetails(
            array('whitelist_email' => $params['email']
            )
        )){
            $query6 =  $this->createConnection()->table($this->localTable)
                    ->select('id', 'email', 'max_block_time', 'ip_address', 'last_order_datetime', 'previous_card');
            $query6->where('email', '=' , $params['email']);
            $list = $query6->get();
            
            if (!empty($list)) {
                return $this->checkIfDateTimeIsWithinRange($list);
            }
        }

        return false;
    }

    protected function getInLocalWhitelistDetails($filterKeys = array()) {

        if (empty($filterKeys))
        {
                return false;
        }
        $whiteList = array();
        $whiteList['whitelist_ip'] = preg_split("/\\r\\n|\\r|\\n/", $this->config['ip_whitelists_local']);
        $whiteList['whitelist_email'] = preg_split("/\\r\\n|\\r|\\n/", $this->config['email_to_whitelists_local']);
        $whiteList['whitelist_card'] = preg_split("/\\r\\n|\\r|\\n/", $this->config['credit_card_whitelists_local']);
        $whiteList['whitelist_domain'] = preg_split("/\\r\\n|\\r|\\n/", $this->config['domain_to_whitelists_local']);

        foreach (array_keys($whiteList) as $key => $value)
        {
                if (empty($whiteList[$value][0]))
                {
                        $whiteList[$value] = false;
                }
        }
        foreach (array_keys($filterKeys) as $value)
        {
                if (!empty($whiteList[$value]) && in_array($filterKeys[$value], $whiteList[$value]))
                {
                        return true;
                }
        }

        return false;
    }

    protected function checkIfDateTimeIsWithinRange($list){
        if(strtotime(current($list)['last_order_datetime']) > strtotime(date("Y-m-d H:i:s"))){
            return true;
        }
        return false;
    }

}
