<?php

class Utils
{
    private $key = "graduaciones.millenium";
    private $CSRF_Token = array("RG9uUXVpam90ZURlbGFNYW5jaGE=",
                                "RWxTZcOxb3JEZUxvc0FuaWxsb3M=",
                                "crsfmobile",
                                "SGFycnlQb3R0ZXJMaWJyb3M=",
                                "TG9zTGlicm9zQ3VsZXJvc0RlQ29laGxv",
                                "TGFCdXNxdWVkYUxpYnJvUGVxdWU=",
                                "RWxQcmluY2lwaXRvTGlicm9QZXF1ZQ==",
                                "RmVybmFuZG9HYWJyaWVsU2lsdmFy",
                                "QXV0b3JEZUVzdGFDb3NheEQ=");
    private $Hash1 = "graduaciones";
    private $Hash2 = "millenium";
    //SOAP Webservice URL
    private $WebserviceURL = "";
    //separated string where all request for email are sent
    public $contactEmails = "";
    //url of association logo, it'll replace in templates for mailing.
    public $urlLogoMail = "";
    //Association name
    public $associationName = "";
    //mailer header
    public $replyHeader = "Precise Translations <no-reply@precisetranslations.com>";
    //url of platform
    public $urlPlatform = "";
    //url for user manual
    public $urlManual = "";
    //base URL
    public $baseUrl = "";
    //Unique Seed
    public $seed = "-GM";
    //lang
    public $lang;



    public function ValidRequest($token){
        @session_start();
        //Validate against CSRF attack!
        if(!isset($_SESSION["UNIQUE-TOKEN$this->seed"])){
            return false;
        }
        //decode a token stack
        $tokens = json_decode($_SESSION["UNIQUE-TOKEN$this->seed"]);
        if (empty($token) || !in_array($token, $tokens)) {
            //you won't attack'
            return false;
        }
        if(!isset($_SESSION["LOGGED-USER-ID$this->seed"]) ||
            !isset($_SESSION["SIMPLE-CSRF-TOKEN$this->seed"]) ||
            !isset($_SESSION["SIMPLE-CSRF-TOKEN$this->seed"])){
            return false;
        }
        return true;
    }

    public function PrettyDate($date, $removeYear, $isLongDate=false){
        if(empty($date) || is_null($date) || $date=="0000-00-00 00:00:00" || $date== "0000-00-00 00:00" || $date=="0000-00-00"){
            return "";
        }
        $months = array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
        $sep = ", ";
        $thisMonth = date("m",strtotime($date));
        $thisDay = date("d",strtotime($date));
        $thisYear = date("Y",strtotime($date));
        return $months[$thisMonth-1]." ". $thisDay.(($removeYear)?"":$sep.$thisYear).(($isLongDate)?date(" g:i A",strtotime($date)):"");
    }


    public function ReturnSessionVar($key){
        @session_start();
        if(isset($_SESSION[$key.$this->seed])){
            return $_SESSION[$key.$this->seed];
        }
        return null;
    }

    public function DestroySessionVar($key){
        @session_start();
        unset($_SESSION[$key.$this->seed]);
    }

    public function SetSessionVar($key, $value){
        @session_start();
        $_SESSION[$key.$this->seed] = $value;
    }

    //required|min-length:5|max-length:100|int|float|date|email|letters|alphanumeric|url
    public function Validate($value, $rules, $human=""){
        $lang = 0;
        $human = explode("|", $human);
        $human_id = $human[$lang];
        $dictionary = array(
            array("debe tener más de", "must have more than"),
            array("caracteres", "characters"),
            array("debe tener menos de", "must have less than"),
            array(),
            array("es obligatorio", "is required"),
            array("debe ser un valor numérico", "must be a numeric value"),
            array("no es una fecha válida", "is not a valid date"),
            array("no es una hora válida", "is not a valid hour"),
            array("no es un email válido", "is not a valid email"),
            array("sólo debe contener letras", "must have only letters"),
            array("sólo debe contener letras y números", "must have only letters and numbers"),
            array("no es un texto válido","is not a valid text"),
            array("no es una URL válida","is not avalid URL")
        );

        $rules_no_satisfied = array();
        $human_id = ((!empty($human_id))?$human_id:$value);
        $rules = explode("|",$rules);
        foreach($rules as $rule){
            //check if is a length validation
            if(strpos($rule, "length")){
                $pair_rule = explode(":",$rule);
                $val = strip_tags($value);
                $len = strlen($val);
                if($pair_rule[0] === "min-length"){
                    if($len<(int)$pair_rule[1]){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[0][$lang]." $pair_rule[1] ".$dictionary[1][$lang]);
                    }
                }else{
                    if($len>(int)$pair_rule[1]){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[2][$lang]." $pair_rule[1] ".$dictionary[1][$lang]);
                    }
                }
            }
            //other rules
            switch($rule){
                case "required":
                    if(empty($value)){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[4][$lang]);
                    }
                    break;
                case "numeric":
                    if(!is_numeric($value)){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[5][$lang]);
                    }
                    break;
                case "date":
                    if(!$this->ValidateDate($value)){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[6][$lang]);
                    }
                    break;
                case "datetime":
                    if (date('Y-m-d H:i', strtotime($value)) != $value) {
                        if (date('Y-m-d H:i:s', strtotime($value)) != $value) {
                            array_push($rules_no_satisfied,"'$human_id' ".$dictionary[6][$lang]);
                        }
                    }
                    break;
                case "time":
                    if(!preg_match("/(2[0-3]|[01][0-9]):([0-5][0-9])/", $value)){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[7][$lang]);
                    }
                    break;
                case "email":
                    if(!filter_var($value, FILTER_VALIDATE_EMAIL)){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[8][$lang]);
                    }
                    break;
                case "letters":
                    if(!preg_match('/^[a-z]+$/i',$value)){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[9][$lang]);
                    }
                    break;
                case "alphanumeric":
                    if (!ctype_alnum($value)) {
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[10][$lang]);
                    }
                    break;
                case "string":
                    if (!preg_match("/^[a-z áéíóúüñÑÁÉÍÓÚÜ]+$/i",$value)){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[11][$lang]);
                    }
                    break;
                case "url":
                    if(empty($value)){
                        break;
                    }
                    if(!filter_var($value, FILTER_VALIDATE_URL)){
                        array_push($rules_no_satisfied,"'$human_id' ".$dictionary[12][$lang]);
                    }
                    break;
                case "json":
                    if(json_decode($value)==null){
                        array_push($rules_no_satisfied,$human_id);
                    }
                    break;
                case "decrypt":
                    if(empty($value) || !is_numeric($this->Decrypt($value))){
                        array_push($rules_no_satisfied,$human_id);
                    }
                    break;
            }
        }
        return $rules_no_satisfied;
    }

    public function getNameTranslation($key){
      switch ($key){
        case "EN":
          return "English";
        case "ES":
          return "Spanish";
        case "AR":
          return "Arabic";
        case "DE":
          return "Deutsch";
        case "FR":
          return "French";
        case "IT":
          return "Italian";
        case "JP":
          return "Japanese";
        case "KO":
          return "Korean";
        case "PT":
          return "Portuguese";
        case "RU":
          return "Russian";
        case "VI":
          return "Vietnamese";
        case "ZH":
          return "Chinese";
      }
      return "";
    }


    public function Encrypt($value)
    {
        //If numeric, we do a simple math algorithm to change value
        if(is_numeric($value)){
            $value = ($value*7+6)*4;
        }
        $result = '';
        for ($i = 0; $i < strlen($value); $i++) {
            $char = substr($value, $i, 1);
            $keychar = substr($this->key, ($i % strlen($this->key)) - 1, 1);
            $char = chr(ord($char) + ord($keychar));
            $result .= $char;
        }
        //To avoid issues with URLS, we change equal sign = to _ and convert the mixed string to base64
        return str_replace(array("=","+"),array("_","-"),base64_encode($result));
    }

    public function Decrypt($value)
    {
        //Inverse method to decrypt a value
        $result = '';
        $value = base64_decode(str_replace("_","=",str_replace("-","+", $value)));
        for ($i = 0; $i < strlen($value); $i++) {
            $char = substr($value, $i, 1);
            $keychar = substr($this->key, ($i % strlen($this->key)) - 1, 1);
            $char = chr(ord($char) - ord($keychar));
            $result .= $char;
        }
        if(is_numeric($result)){
            $result = (($result/4)-6)/7;
        }
        return $result;
    }

    public function GenerateLongString($lng)
    {
        $catalog = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
        $longString = strlen($catalog);
        $newString = "";
        $long = $lng;
        for ($i = 1; $i <= $long; $i++) {
            $pos = rand(0, $longString - 1);
            $newString .= substr($catalog, $pos, 1);
        }
        return $newString;
    }

    public function GenerateBasicString($lng)
    {
        $catalog = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        $longString = strlen($catalog);
        $newString = "";
        $long = $lng;
        for ($i = 1; $i <= $long; $i++) {
            $pos = rand(0, $longString - 1);
            $newString .= substr($catalog, $pos, 1);
        }
        return $newString;
    }

    public function SanitizeString($value){
        $catalog = array("--", "/*", "*/");
        return strip_tags(str_replace($catalog,"",trim(addslashes(str_replace("'","´",$value)))));
    }

    public function StripSlash($value){
        return str_replace("'","´",$value);
    }

    public function ReplaceSpecialChars($value){
        $definition = array("u00e1", "u00a1", "u00e9", "u00ed","u00f3","u00fa","u00b4","u00f1","\\","u00c3","u00b3", "u00c1","u00c9","u00cd","u00d3","u00da","u00d1");
        $result = array("á","¡","é","í","ó","ú","'","ñ","","ó","","À","È","Ì","Ò","Ù");

        return str_replace($definition,$result,$value);
    }

    public function ConvertLinksFromString($string){
        $url = '~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i';
        return preg_replace($url, '<a href="$0" target="_blank" title="$0">$0</a>', $string);
    }

    public function EncryptWithoutReverse($value){
        $step1 = md5 ($value);
        $step2 = crc32($step1);
        $step3 = crypt($step2, $this->Hash1);
        return sha1($this->Hash2.$step3);
    }

    public function GetWebservicesURL(){
        return $this->WebserviceURL;
    }

    public function SeekCRSFToken($value){
        return in_array($value, $this->CSRF_Token);
    }

    public function ReturnCSRFToken(){
        return $this->CSRF_Token[rand(1, count($this->CSRF_Token)-1)];
    }


    public function ReturnNewTokenInForm(){
        //We use a stack, maximun of 10 request tokens, avoiding possible damages in information due to open many tabs
        @session_start();
        $stack = array();
        if(isset($_SESSION["UNIQUE-TOKEN$this->seed"])){
            $stack = json_decode($_SESSION["UNIQUE-TOKEN$this->seed"]);
            if($stack==null){
                $stack = array();
            }
        }
        $tkn = base64_encode(openssl_random_pseudo_bytes(32));
        array_push($stack, $tkn);
        if(count($stack)>10){
            array_shift ($stack);
        }
        $_SESSION["UNIQUE-TOKEN$this->seed"] = json_encode($stack);
        return $tkn;
    }

    public function GetFileExtension($str){
        $tmp = explode('.', $str);
        return end($tmp);
    }

    public function ValidateDate($date, $includeTime=false)
    {
        if($includeTime){
            $d = DateTime::createFromFormat('Y-m-d H:m:s', $date);
            return $d && $d->format('Y-m-d H:m:s') == $date;
        }
        $d = DateTime::createFromFormat('Y-m-d', $date);
        return $d && $d->format('Y-m-d') == $date;
    }

    public function CompressImage($source,$destination,  $name, $quality)
    {
        $newname = $this->GenerateLongString(15).".".$this->GetFileExtension($name);
        $info = getimagesize($source);
        if ($info['mime'] == 'image/jpeg')
            $image = imagecreatefromjpeg($source);
        elseif ($info['mime'] == 'image/gif')
            $image = imagecreatefromgif($source);
        elseif ($info['mime'] == 'image/png'){
            $im = imagecreatefrompng($source);
            $quality = 5; //0 - 9 (0= no compression, 9 = high compression)
            imagealphablending($im, true);
            imagesavealpha($im, true);
            imagepng($im, $destination."/".$newname, $quality);  //leave out filename if you want it to output to the buffer
            imagedestroy($im);

            return $newname;
        }
        else
            return "";
        imagejpeg($image, $destination."/".$newname, $quality);
        return $newname;
    }


    public function Clean($string) {
        $string = str_replace(array('[\', \']'), '', $string);
        $string = preg_replace('/\[.*\]/U', '', $string);
        $string = preg_replace('/&(amp;)?#?[a-z0-9]+;/i', '-', $string);
        $string = htmlentities($string, ENT_COMPAT, 'utf-8');
        $string = preg_replace('/&([a-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig|quot|rsquo);/i', '\\1', $string );
        $string = preg_replace(array('/[^a-z0-9]/i', '/[-]+/') , '-', $string);
        return strtolower(trim($string, '-'));
    }

    public function DistanceBetweenCoordinates ($lat1, $lon1, $lat2, $lon2, $unit) {
        $theta = $lon1 - $lon2;
        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
        $dist = acos($dist);
        $dist = rad2deg($dist);
        $miles = $dist * 60 * 1.1515;
        $unit = strtoupper($unit);
        if ($unit == "K") {
            return ($miles * 1.609344);
        } else if ($unit == "N") {
            return ($miles * 0.8684);
        } else {
            return $miles;
        }
    }

    public function  GetBetweenTwoDates($sStartDate, $sEndDate, $type){
        $sStartDate = date("Y-m-d", strtotime($sStartDate));
        $sEndDate = date("Y-m-d", strtotime($sEndDate));
        $response[] = $sStartDate;
        $sCurrentDate = $sStartDate;
        while($sCurrentDate < $sEndDate){
            $sCurrentDate = date("Y-m-d", strtotime("+1 ".$type, strtotime($sCurrentDate)));
            if($sCurrentDate < $sEndDate){
                $response[] = $sCurrentDate;
            }

        }
        return $response;
    }

}