<?php namespace urcstring;

/*
get_random_string()
get_random_string('09')
get_random_string('azAZ09')
get_random_string('azAZ09$')
*/

class StringGenerator {

	public static function doGen($len = 10, $type = '', $must = 0) {
		$lowercase = 'abcdefghijklmnopqrstuvwxyz';
	    $uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
	    $numeric = '0123456789';
	    $special = '`~!@#$%^&*()-_=+\\|[{]};:\'",<.>/?';
	    $key = '';
	    $token = '';

	    $lowerUse = 0;
	    $upperUse = 0;
	    $numUse = 0;
	    $specUse = 0;

	    if ($type == '') {
	        $key = $lowercase.$uppercase.$numeric;
	        $numUse = 1;
	    } else {
	        if (strpos($type,'09') > -1) {
	        	$key .= $numeric;
	        	$numUse = 1;
	        }
	        if (strpos($type,'az') > -1) {
	        	$key .= $lowercase;
	        	$lowerUse = 1;
	        }
	        if (strpos($type,'AZ') > -1) {
	        	$key .= $uppercase;
	        	$upperUse = 1;
	        }
	        if (strpos($type,'$') > -1) {
	        	$key .= $special;
	        	$specUse = 1;
	        }
	    }

	    if($must) {

	    	$need = $lowerUse + $upperUse + $numUse + $specUse;
	    	$newlen = $len-$need;

	    	for ($i = 0; $i < $newlen; $i++) {
		        $token .= $key[mt_rand(0, strlen($key) - 1)];
		    }

		    if($lowerUse) {
		    	$token .= $key[mt_rand(0, strlen($lowercase) - 1)];	
		    }
		    if($upperUse) {
		    	$token .= $key[mt_rand(0, strlen($uppercase) - 1)];	
		    }
		    if($numUse) {
		    	$token .= $key[mt_rand(0, strlen($numeric) - 1)];	
		    }
		    if($specUse) {
		    	$token .= $key[mt_rand(0, strlen($special) - 1)];	
		    }

		    return str_shuffle($token);
	    }
	    else {
		    for ($i = 0; $i < $len; $i++) {
		        $token .= $key[mt_rand(0, strlen($key) - 1)];
		    }

		    return $token;
		}
	}

	public static function xmlToArray($xml, $options = array()) {
	    $defaults = array(
	        'namespaceSeparator' => ':',//you may want this to be something other than a colon
	        'attributePrefix' => '@',   //to distinguish between attributes and nodes with the same name
	        'alwaysArray' => array(),   //array of xml tag names which should always become arrays
	        'autoArray' => true,        //only create arrays for tags which appear more than once
	        'textContent' => '$',       //key used for the text content of elements
	        'autoText' => true,         //skip textContent key if node has no attributes or child nodes
	        'keySearch' => false,       //optional search and replace on tag and attribute names
	        'keyReplace' => false       //replace values for above search values (as passed to str_replace())
	    );
	    $options = array_merge($defaults, $options);
	    $namespaces = $xml->getDocNamespaces();
	    $namespaces[''] = null; //add base (empty) namespace
	 
	    //get attributes from all namespaces
	    $attributesArray = array();
	    foreach ($namespaces as $prefix => $namespace) {
	        foreach ($xml->attributes($namespace) as $attributeName => $attribute) {
	            //replace characters in attribute name
	            if ($options['keySearch']) $attributeName =
	                    str_replace($options['keySearch'], $options['keyReplace'], $attributeName);
	            $attributeKey = $options['attributePrefix']
	                    . ($prefix ? $prefix . $options['namespaceSeparator'] : '')
	                    . $attributeName;
	            $attributesArray[$attributeKey] = (string)$attribute;
	        }
	    }
	 
	    //get child nodes from all namespaces
	    $tagsArray = array();
	    foreach ($namespaces as $prefix => $namespace) {
	        foreach ($xml->children($namespace) as $childXml) {
	            //recurse into child nodes
	            $childArray = StringGenerator::xmlToArray($childXml, $options);

	            $childTagName = '';
	            $childProperties = '';
	            list($childTagName, $childProperties) = each($childArray);
	 
	            //replace characters in tag name
	            if ($options['keySearch']) $childTagName =
	                    str_replace($options['keySearch'], $options['keyReplace'], $childTagName);
	            //add namespace prefix, if any
	            if ($prefix) $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName;
	 
	            if (!isset($tagsArray[$childTagName])) {
	                //only entry with this key
	                //test if tags of this type should always be arrays, no matter the element count
	                $tagsArray[$childTagName] =
	                        in_array($childTagName, $options['alwaysArray']) || !$options['autoArray']
	                        ? array($childProperties) : $childProperties;
	            } elseif (
	                is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName])
	                === range(0, count($tagsArray[$childTagName]) - 1)
	            ) {
	                //key already exists and is integer indexed array
	                $tagsArray[$childTagName][] = $childProperties;
	            } else {
	                //key exists so convert to integer indexed array with previous value in position 0
	                $tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties);
	            }
	        }
	    }
	 
	    //get text content of node
	    $textContentArray = array();
	    $plainText = trim((string)$xml);
	    if ($plainText !== '') $textContentArray[$options['textContent']] = $plainText;
	 
	    //stick it all together
	    $propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '')
	            ? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText;
	 
	    //return node as array
	    return array(
	        $xml->getName() => $propertiesArray
	    );
	}

	public static function gen_uuid() {

		//if (!function_exists('uuid_create')) {

			$data = openssl_random_pseudo_bytes(16);
			assert(strlen($data) == 16);

		    $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
		    $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10

		    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
		/*
		}

		$context = '';
		$uuid = '';
	    
	    uuid_create($context);

	    uuid_make($context, UUID_MAKE_V4);

	    uuid_export($context, UUID_FMT_STR, $uuid);
	    return trim($uuid);
	    */
	}

	public static function gen_msg_id() {

		return StringGenerator::doGen(8);
	}

	public static function gen_tmp_mac($systemId) {

		$data = openssl_random_pseudo_bytes(16);
		assert(strlen($data) == 16);

	    $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
	    $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10

	    return substr(sprintf('TMP_%d_%s', (int)$systemId, bin2hex($data)), 0, 32);
	}
}

