<?php
include_once "../../system/lib/config.php";

class ConnectSite extends System {
    
    /**
     * 
     * @var string
     */
    private $requestMethod             = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $contentType               = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $payload                   = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $connectURL                = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $connectRequestParams      = NO_STRING;
    
    /**
     * 
     * @var string
     */
    private $connectRequestMethod      = NO_STRING;
    
    /**
     * 
     * @var array
     */
    private $connectRequestHeader      = [];
    
    public function __construct(){
        parent::__construct();
        
        $this -> setParameter();
        $this -> validation();
    }
    
    private function setParameter(){
        $this -> requestMethod  = $this -> getColumnData($_SERVER, "REQUEST_METHOD");
        $this -> contentType    = $this -> getColumnData($_SERVER, "CONTENT_TYPE");
        
        $this -> payload        = file_get_contents("php://input");
    }
    
    private function validation(){
        $validationRemarks = [];
                
        if(strcasecmp($this -> requestMethod, "POST") !== 0){
            $validationRemarks[] = json_encode([
                "code" => "001",
                "message" => "Invalid Request Type {$this -> requestMethod}"
            ]);
        }
        
        if(!$this -> checkJSONString($this -> payload)){
            $validationRemarks[] = json_encode([
                "code" => "002",
                "message" => "Payload is not a JSON String"
            ]);
        }else
            $this -> authenticatePayload();
        
        if($this -> connectURL == NO_STRING){
            $validationRemarks[] = json_encode([
                "code" => "003",
                "message" => "No Callback URL Specified"
            ]);
        }
        
        if($this -> contentType != "application/json"){
            $validationRemarks[] = json_encode([
                "code" => "004",
                "message" => "Invalid Content Type: {$this -> contentType}"
            ]);
        }
        
        $devSetting = $this -> getRowData($this -> accessSelect("SELECT_DEV_SETTING", ["tester_tool_conf"]));
        
        if($this -> isLoopData($devSetting)){
            if($this -> checkJSONString($this -> getColumnData($devSetting, "dev_setting_value"))){
                $devSetting = json_decode($this -> getColumnData($devSetting, "dev_setting_value"));
                
                $ipAddresses    = explode(",", $devSetting -> ip_address);
                $remoteAddress  = $this -> getColumnData($_SERVER, "REMOTE_ADDR");
                
                if(!in_array($remoteAddress, $ipAddresses)){
                    $validationRemarks[] = json_encode([
                        "code" => "005",
                        "message" => "Invalid IP Address: {$remoteAddress}"
                    ]);
                }
            }
        }
        
        if($this -> isLoopData($validationRemarks)){
            echo "<pre>";
            die(print_r($validationRemarks, true));
        }
    }
    
    private function authenticatePayload(){
        $this -> payload = json_decode($this -> payload);
        
        if(isset($this -> payload -> connectUrl)){
            $this -> connectURL = $this -> payload -> connectUrl;
        }
        
        if(isset($this -> payload -> requestMethod)){
            $this -> requestMethod = $this -> payload -> requestMethod;
        }
        
        if(isset($this -> payload -> requestParams)){
            $tempRequestParam = $this -> payload -> requestParams;
            
            if(is_object($tempRequestParam))
                $this -> connectRequestParams = http_build_query($tempRequestParam);
            else if(is_string($tempRequestParam))
                $this -> connectRequestParams = $tempRequestParam;
        }
        
        if(isset($this -> payload -> requestHeaders)){
            if(is_array($this -> payload -> requestHeaders))
                $this -> connectRequestHeader = $this -> payload -> requestHeaders;
        }
    }
    
    private function processRequest(){
        $handle = curl_init($this -> connectURL);
        
        curl_setopt($handle, CURLOPT_CUSTOMREQUEST, $this -> requestMethod);
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($handle, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($handle, CURLOPT_ENCODING, "utf8");
        curl_setopt($handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        
        if($this -> isLoopData($this -> connectRequestHeader)){
            curl_setopt($handle, CURLOPT_HTTPHEADER, $this -> connectRequestHeader);
        }
        
        if($this -> connectRequestParams != NO_STRING){
            curl_setopt($handle, CURLOPT_POSTFIELDS, $this -> connectRequestParams);
        }
        
        $output = curl_exec($handle);
        
        if($err = curl_error($handle)){
            $output = $err;
        }
        
        curl_close($handle);
        
        return $output;
    }
    
    public function listen(){        
        $serverName = $this -> getColumnData($_SERVER, "SERVER_NAME");
        
        $requestee = $this -> getColumnData(parse_url($this -> connectURL), "host");
        
        $processingDetails = [
            "Requester_Name" => $serverName,
            "Requester_IP" => gethostbyname($serverName),
            "Requestee_Name" => $requestee,
            "Requestee_IP" => gethostbyname($requestee),
            "Requestee_URL" => $this -> connectURL,
            "Request_Headers" => $this -> connectRequestHeader,
            "Request_Params" => $this -> connectRequestParams,
        ];
        
        print_r($processingDetails);
        
        echo "\n\nResult:\n";
        echo $this -> processRequest();
    }
}

$connect = new ConnectSite();
$connect -> listen();