<?php 

namespace NPS\Etc;

/**
 * Auxiliary string processing functions
 * @author Lukas Korinek
 */
class Strings
{
    const GIT_ANY = 0;
    const GIT_SSH = 1;
    const GIT_HTTPS = 2;

    /**
     * Creates a random string of an arbitrary length
     * @param int $length
     * @return string
     */
    public static function random($length = 15)
    {
        $characters = array_map(function($index)
        {
            $type = rand(0, 3);
            if($type == 1)
            {
                return chr(rand(ord('0'), ord('9')));
            }
            else if($type == 2)
            {
                return chr(rand(ord('A'), ord('Z')));
            }

            return chr(rand(ord('a'), ord('z')));
        }, range(0, $length - 1));

        return implode('', $characters);
    }

    /**
     * Checks if the haystack starts with the needle
     * @param string $needle 
     * @param string $haystack 
     * @return bool
     */
    public static function starts($needle, $haystack)
    {
        return strpos($haystack, $needle) === 0;
    }

    /**
     * Checks if the haystack contains the needle
     * @param string $needle
     * @param string $haystack 
     * @return bool
     */
    public static function contains($needle, $haystack)
    {
        return strpos($haystack, $needle) !== FALSE;
    }

    /**
     * Checks if the haystack ends with the needle
     * @param string $needle
     * @param string $haystack 
     * @return bool
     */
    public static function ends($needle, $haystack)
    {
        $offset = -1;
        while(($new = strpos($haystack, $needle, $offset + 1)) !== FALSE)
        {
            $offset = $new;
        }

        return $offset === (strlen($haystack) - strlen($needle));
    } 

    /**
     * Replaces all occurences of a needle in the haystack with the replacement
     * Serves for future standardization (possible encoding issues)
     * @param string|array $needle 
     * @param string $replacement
     * @param string $haystack
     * @return string
     */
    public static function replace($needle, $replacement, $haystack)
    {
        return str_replace($needle, $replacement, $haystack);
    }   

    /**
     * Generates a hash which can be used for various token purposes
     * @param array $unique Unique combination array to make the hash unique
     * @return string
     */
    public static function generateHash(array $unique)
    {
        $str = self::random(10) . '|' . implode('-', $unique);
        return hash('sha512', $str);
    }

    /**
     * Adds parameters to an URL
     * @param string $url
     * @param array $parameters
     * @return string
     */
    public static function urlQuery($url, array $parameters)
    {
        return $url . (parse_url($url, PHP_URL_QUERY) ? '&' : '?') . http_build_query($parameters);
    }

    /**
     * Decides if a string can be used as a password
     * @param string $str 
     * @return bool
     */
    public static function isStrongPassword($str)
    {
        // Is at least 8 characters long
        if(strlen($str) < 8)
        {
            return false;
        }

        if(!preg_match("/\d+/", $str))
        {
            return false;
        }

        if(!preg_match("/[a-zA-Z]+/", $str))
        {
            return false;
        }

        return true;
    }

    /**
     * Sanitizes string to be consisting only from ASCII alphanumeric chars and hyphens
     * @param string $string 
     * @return string
     */
    public static function sanitizeASCII($string)
    {
        // Filter out non ASCII chars
        $arr = array_filter(str_split($string), function($char)
        {
            return (ctype_alnum($char) || $char == ' ') && ord($char) < 128;
        });
        $str = trim(implode($arr));

        // Replace spaces and underscores with hyphens
        $str = str_replace('  ', ' ', $str);
        $str = str_replace(' ', '-', $str);
        $str = str_replace('_', '-', $str);

        return strtolower($str);
    }

    /**
     * Decides whether the string as a good candidate for a Git url
     * e.g.
     * https://korinek111@bitbucket.org/mrrootcze/npsknowledge.git
     * git@bitbucket.org:mrrootcze/npsknowledge.git
     * @todo Extend for different formats (https://stackoverflow.com/questions/2514859/regular-expression-for-git-repository)
     * @param string $string 
     * @param int $type Type of the URL
     * @return bool True on valid string
     */
    public static function isGitUrl($string, $type)
    {
        $ssh = !!preg_match("/^[A-Za-z0-9_ ]+@[:.A-Za-z0-9_ \/]+\.git\/{0,1}$/", $string);
        $https = !!preg_match("/^https:\/\/[A-Za-z0-9_ ]+@[:.A-Za-z09_ \/]+\.git\/{0,1}$/", $string);

        if($type == self::GIT_HTTPS)
        {
            return $https;
        }

        if($type == self::GIT_SSH)
        {
            return $ssh;
        }

        return $ssh || $https;
    }
}

