<?php

/**

 * @author    ThemePunch <info@themepunch.com>

 * @link      https://www.themepunch.com/

 * @copyright 2019 ThemePunch

 */



if(!defined('ABSPATH')) exit();



if(!class_exists('RSColorpicker')){

	class RSColorpicker {

		

		/**

		 * @since 5.3.1.6

		 */

		public function __construct(){

		}

		

		/**

		 * get a value

		 * @since 5.3.1.6

		 */

		public static function get($val){

	        if(!$val || empty($val)) return 'transparent';

	        $process = RSColorpicker::process($val, true);

	        return $process[0];

	    }

		

		/**

		 * parse a color

		 * @since 5.3.1.6

		 */

		public static function parse($val, $prop, $returnColorType){

			$val = RSColorpicker::process($val, true);

			$ar = array();

			

			if(!$prop){

				$ar[0] = $val[0];	

			}else{

				$ar[0] = $prop . ': ' . $val[0] . ';';

			}

			

			if($returnColorType) $ar[1] = $val[1];

			

			return $ar;

		

		}





		/**

		 * convert a color

		 * @since 5.3.1.6

		 */

		public static function convert($color, $opacity = '100'){

			if($opacity == 'transparent'){

				return 'rgba(0,0,0,0)';

			}

			if($color == '') return '';

			if(strpos($color, '[{') !== false || strpos($color, 'gradient') !== false) return RSColorpicker::get($color);

			

			if(!is_bool($opacity) && ''.$opacity === '0'){

				return 'transparent';

			} 



			if($opacity == -1 || !$opacity || empty($opacity) || !is_numeric($opacity) || $color == 'transparent' || $opacity === 1 || $opacity === 100){

				if(strpos($color, 'rgba') === false && strpos($color, '#') !== false){

					return RSColorpicker::processRgba(RSColorpicker::sanitizeHex($color), $opacity);

				}else{

					$color = RSColorpicker::process($color, true);

					return $color[0];

				}

			}



			$opacity = floatval($opacity);

			if($opacity < 1) $opacity = $opacity * 100;

			$opacity = round($opacity);

			$opacity = ($opacity > 100) ? 100 : $opacity;

			$opacity = ($opacity < -1) ? 0 : $opacity;



			if($opacity === 0) return 'transparent';



			if(strpos($color, '#') !== false){

				return RSColorpicker::processRgba(RSColorpicker::sanitizeHex($color), $opacity);

			}else{

				$color = RSColorpicker::rgbValues($color, 3);

				return RSColorpicker::rgbaString($color[0], $color[1], $color[2], $opacity);

			}

		}





		/**

		 * process color

		 * @since 5.3.1.6

		 */

		public static function process($clr, $processColor = false){

			if(!is_string($clr)){

				if($processColor) $clr = RSColorpicker::sanatizeGradient($clr);

				return array(RSColorpicker::processGradient($clr), 'gradient', $clr);

			}elseif(trim($clr) == 'transparent'){

				return array('transparent', 'transparent');

			}elseif(strpos($clr, '[{') !== false){

				try{

					$clr = json_decode(str_replace("amp;", '',str_replace("&", '"', $clr)), true);



					if($processColor) $clr = RSColorpicker::sanatizeGradient($clr);



					return array(RSColorpicker::processGradient($clr), 'gradient', $clr);

				}catch(Exception $e){

					return array(

						'linear-gradient(0deg, rgb(255, 255, 255) 0%, rgb(0, 0, 0) 100%)', 

						'gradient',

						array(

							'type' => 'linear',

							'angle' => '0',

							'colors' => array(

								array(

									'r' => '255',

									'g' => '255',

									'b' => '255',

									'a' => '1',

									'position' => '0',

									'align' => 'bottom'

								),

								array(

									'r' => '0',

									'g' => '0',

									'b' => '0',

									'a' => '1',

									'position' => '100',

									'align' => 'bottom'

								)

							)

						)

					);

				}

			}elseif(strpos($clr, '-gradient') !== false){

				

				// gradient was not stored as a JSON string for some reason and needs to be converted

				$reversed = RSColorpicker::reverseGradient($clr);

				return array(RSColorpicker::processGradient($reversed), 'gradient_css', $reversed);

				

			}elseif(strpos($clr,'#') !== false){

				

				return array(RSColorpicker::sanitizeHex($clr), 'hex');

				

			}elseif(strpos($clr,'rgba') !== false){

				$clr = preg_replace('/\s+/', '', $clr);

				

				// fixes 'rgba(0,0,0,)' issue

				preg_match('/,\)/', $clr, $matches);

				if(!empty($matches)) {

					$clr = explode(',)', $clr);

					$clr = $clr[0] . ',1)';

				}

				

				return array($clr, 'rgba');

			}else{

				$clr = preg_replace('/\s+/', '', $clr);

				return array($clr, 'rgb');

			}

		}



		/**

		 * sanitize a gradient

		 * @since 5.3.1.6

		 */

		public static function sanatizeGradient($obj){

			$colors = $obj['colors'];

			$len = count($colors);

			$ar = array();



			for($i = 0; $i < $len; $i++){

				$cur = $colors[$i];

				unset($cur['align']);

				

				if(is_bool($cur['a'])) $cur['a'] = $cur['a'] ? 1 : 0;

				$cur['a'] = RSColorpicker::sanitizeAlpha($cur['a']);

				

				$cur['r'] = intval($cur['r']);

				$cur['g'] = intval($cur['g']);

				$cur['b'] = intval($cur['b']);

				$cur['position'] = intval($cur['position']);

				

				if(isset($prev)){

					if(json_encode($cur) !== json_encode($prev)){

						$ar[] = $cur;

					}

				}else{

					$ar[] = $cur;

				}

				$prev = $cur;

			}

			

			$obj['colors'] = $ar;

			

			return $obj;

		}

		

		/**

		 * cleans up the alpha value for comparison operations

		 * @since 6.0

		 */

		 public static function sanitizeAlpha($alpha){

			$alpha = floatval($alpha);

			$alpha = min($alpha, 1);

			$alpha = max($alpha, 0);

			$alpha = number_format($alpha, 2, '.', '');

			$alpha = preg_replace('/\.?0*$/', '', $alpha);

			

			return floatval($alpha);

		}

		

		/**

		 * accounting for cases where gradient doesn't exist as a JSON Object from previous templates for some reason

		 * @since 6.0

		 */

		public static function reverseGradient($str){

			

			// hsl colors not supported yet

			if(strpos($str, 'hsl') !== false) return $str;

			

			$str = str_replace('/\-moz\-|\-webkit\-/', '', $str);

			$str = str_replace('to left', '90deg', $str);

			$str = str_replace('to bottom', '180deg', $str);

			$str = str_replace('to top', '0deg', $str);

			$str = str_replace('to right', '270deg', $str);

			$str = str_replace(';', '', $str);

			

			$gradient = explode('-gradient(', $str);

			if(count($gradient) < 2) return $str;

			

			$grad = trim($gradient[1]);

			$degree = '0';

			

			if(strpos($grad, 'ellipse at center') === false){

				

				if(strpos($grad, 'deg') !== false){

					$grad = explode('deg', $grad);

					$degree = trim($grad[0]);

					$grad = trim($grad[1]);

				}

				

			}else{

				$grad = str_replace('ellipse at center', '', $grad);

			}

			

			if($grad[0] === ',') $grad = ltrim($grad, ',');

			if($grad[strlen($grad) - 1] === ',') $grad = rtrim($grad, ',');

			

			$colors = explode('%', $grad);

			$list = array();

			

			array_pop($colors);

			$prev = false;

			

			foreach($colors as $clr) {

				

				$clr = trim($clr);

				$perc = '';

				

				if($clr[0] === ',') $clr = ltrim($clr, ',');

				if(strpos($clr, ' ') === false) return $str;

				

				$perc = explode(' ', $clr);

				$perc = $perc[count($perc) - 1];

				

				$leg = strlen($clr);

				$index = 0;

				

				while($leg--){

					$index = $leg;

					if($clr[$leg] === ' ') break;

				}

				

				$clr = substr($clr, 0, $index);

				preg_match('/\)/', $clr, $matches);

				

				if(!empty($matches)) {

					$clr = explode(')', $clr);

					$clr = trim($clr[0]) . ')';

				}else{

					$clr = explode(' ', $clr);

					$clr = trim($clr[0]);

				}

				

				$tpe = RSColorpicker::process($clr, false);

				if($tpe[1] === 'hex'){

					$clr = RSColorpicker::sanitizeHex($clr);

					$clr = RSColorpicker::processRgba($clr);

				}

				

				if($prev && $prev === $clr) continue;

				$prev = $clr;

				

				$clr = RSColorpicker::rgbValues($clr, 4);

				$list[] = array('r' => $clr[0], 'g' => $clr[1], 'b' => $clr[2], 'a' => $clr[3], 'position' => $perc, 'align' => 'top');

			

			}

			

			return array('type' => trim($gradient[0]), 'angle' => $degree, 'colors' => $list);

		

		}

		

		/**

		 * create the gradient

		 * @since 6.0

		 */

		 public static function easeGradient(&$gradient){

			include_once(RS_PLUGIN_PATH . 'includes/coloreasing.class.php');

			if(class_exists('RSColorEasing')){

				$strength = (intval($gradient['strength']) * 0.01) * 15;

				$easing = $gradient['easing'];

				$points = $gradient['colors'];

				

				$len = count($points) - 1;

				$ar = array();



				for($i = 0; $i < $len; $i++){

					$ar[] = $points[$i];

					RSColorEasing::insertPoints($points[$i], $points[$i + 1], $ar, $easing, $strength);

				}



				$ar[] = $points[$len];

				$gradient['colors'] = $ar;

			}

		 }



		/**

		 * create the gradient

		 * @since 5.3.1.6

		 */

		public static function processGradient($obj){

			

			if(!is_array($obj)) return 'transparent';

			if(array_key_exists('easing', $obj) && $obj['easing'] !== 'none') {

				RSColorpicker::easeGradient($obj);

			}

			

			$tpe = $obj['type'];

			$begin = $tpe . '-gradient(';

			

			if($tpe === 'linear') {

				$angle = intval($obj['angle']);

				$middle = $angle !== 180 ? $angle . 'deg, ' : '';

			}

			else {

				$middle = 'ellipse at center, ';

			}



			$colors = $obj['colors'];

			$end = '';

			

			$i = 0;

			foreach($colors as $clr){

				if($i > 0) $end .= ', ';

				$end .= 'rgba(' . $clr['r'] . ',' . $clr['g'] . ',' . $clr['b'] . ',' . $clr['a'] . ') ' . $clr['position'] . '%';

				$i++;

			}

			

			return $begin . $middle . $end . ')';

			

		}





		/**

		 * get rgb values

		 * @since 5.3.1.6

		 */

		public static function rgbValues($values, $num){

			$values = substr( $values, strpos($values, '(') + 1  , strpos($values, ')')-strpos($values, '(') - 1 );

			$values = explode(",", $values);

			

			if(count($values) == 3 && $num == 4) $values[3] = '1';

			for($i = 0; $i < $num; $i++){

				if(isset($values[$i])) $values[$i] = trim($values[$i]);

			}

			

			if(count($values) < $num){

				$v = count($values)-1;

				for($i = $v; $i < $num; $i++){

					$values[$i] = $values[0];

				}

			}

			

			return $values;

		}



		/**

		 * get an rgba string

		 * @since 5.3.1.6

		 */

		public static function rgbaString($r, $g, $b, $a){

			if($a > 1){

				$a = ''.number_format($a * 0.01, 2, '.', '');

	      		$a = str_replace('.00', '', $a);

	      	}

			return 'rgba(' . $r . ',' . $g . ',' . $b . ',' . $a . ')';

		}



		/**

		 * change rgb to hex

		 * @since 5.3.1.6

		 */

		public static function rgbToHex($clr){

			$values = RSColorpicker::rgbValues($clr, 3);

			return RSColorpicker::getRgbToHex($values[0], $values[1], $values[2]);

		}



		/**

		 * change rgba to hex

		 * @since 5.3.1.6

		 */

		public static function rgbaToHex($clr){

			$values = RSColorpicker::rgbValues($clr, 4);

			return RSColorpicker::getRgbToHex($values[0], $values[1], $values[2]);

		}



		/**

		 * get opacity

		 * @since 5.3.1.6

		 */

		public static function getOpacity($val){

			$rgb = RSColorpicker::rgbValues($val, 4);

			return intval($rgb[3] * 100, 10) + '%';

		}



		/**

		 * change rgb to hex

		 * @since 5.3.1.6

		 */

		public static function getRgbToHex($r, $g, $b){

			$rgb = array($r, $g, $b);

			$hex = "#";

	   		$hex .= str_pad(dechex($rgb[0]), 2, "0", STR_PAD_LEFT);

	   		$hex .= str_pad(dechex($rgb[1]), 2, "0", STR_PAD_LEFT);

	   		$hex .= str_pad(dechex($rgb[2]), 2, "0", STR_PAD_LEFT);

	   		return $hex;

		}



		/**

		 * join it together to be rgba

		 * @since 5.3.1.6

		 */

		public static function joinToRgba($val){

			$val = explode('||', $val);

			return RSColorpicker::convert($val[0], $val[1]);

		}

		

		/**

		 * rgb to rgba

		 * @since 6.0

		 */

		public static function rgbToRgba($val){

			

			$val = RSColorpicker::rgbValues($val, 4);

			return RSColorpicker::rgbaString($val[0], $val[1], $val[2], $val[3]);

			

		}

		

		/**

		 * convert rgba with 100% opacity to hex

		 * @since 6.0

		 */

		public static function trimHex($color) {

			

			$color = trim($color);

			if(strlen($color) !== 7) return $color;

			

			$clr = str_replace('#', '', $color);

			$char = $clr[0];

			

			for($i = 1; $i < 6; $i++) {

				if($clr[$i] !== $char) return $color;

				$char = $clr[$i];

			}

			

			return '#' . substr($clr, 0, 3);

			

		}

		

		/**

		* the legacy opacity to rgba conversions and also checks for gradients

		* @since: 6.0

		*/

		public function correctValue($color, $opacity = false) {

			

			if(!is_string($color)) return $color; // unknown value

			

			// gradients can exist as a JSON string or a CSS string

			// when they exist as a CSS string it is a result of a bug from 5.0 

			if(strpos($color, '[{') === false && strpos($color, 'gradient') === false) {

				

				if($opacity === false) return $color; // normal color

				return RSColorpicker::convert($color, $opacity); // legacy conversion

				

			}

			

			return $color; // gradient

		

		}

		

		/**

		 * useful when you need to compare two values and also for smallest print size

		 * for example, this function will convert both"

		 * "rgba(255,255, 255,1)" and "#FFFFFF" to "#FFF"

		 * @since: 6.0

		 */  

		public static function normalizeColor($color) {



			$color = RSColorpicker::process($color, true);

			$clr = $color[0];

			$tpe = $color[1];

			$processed = true;

			

			if($tpe === 'hex') {

				$clr = RSColorpicker::processRgba($clr, true);

				$processed = true;

			}

			else if($tpe === 'rgb') {

				$clr = RSColorpicker::rgbToRgba($clr);

			}

			else if($tpe === 'rgba') {

				$clr = preg_replace('/\s+/', '', $clr);

				

			}

			else {

				$processed = false;

			}

			

			if($processed) $clr = RSColorpicker::sanitizeRgba($clr);

			return $clr;

			

		}

		

		/**

		 * normalize colors for comparison

		 * @since: 6.0

		 */  

		public static function normalizeColors($color) {

			

			if(is_object($color)) $color = (array)$color;

			if(is_array($color)) {

				$total = count($color);

				for($i = 0; $i < $total; $i++) $color[$i] = RSColorpicker::normalizeColor($color[$i]);

			}

			else {

				$color = RSColorpicker::normalizeColor($color);

			}

			

			return $color;

			

		}

		

		/**

		 * convert rgba with 100% opacity to hex

		 * @since 6.0

		 */

		public static function sanitizeRgba($color, $opacity = false) {

			

			if($opacity) {

				$color = RSColorpicker::rgbaToHex($color);

				$color = RSColorpicker::trimHex($color);

			}

			else {

				$opacity = RSColorpicker::rgbValues($color, 4);

				if($opacity[3] === '1') {

					$color = RSColorpicker::rgbaToHex($color);

					$color = RSColorpicker::trimHex($color);

				}

			}

			

			return $color;

			

		}



		/**

		 * process rgba

		 * @since 5.3.1.6

		 */

		public static function processRgba($hex, $opacity = false){

			

			$hex = trim(str_replace('#', '' , $hex));

			

			$rgb = $opacity!==false ? 'rgba' : 'rgb';  

			$r = hexdec(substr($hex,0,2));

	      	$g = hexdec(substr($hex,2,2));

	      	$b = hexdec(substr($hex,4,2));

	      	

	      	$color = $rgb . "(" . $r . "," . $g . "," . $b ;



	      	if($opacity!==false){

	      		if($opacity > 1)

	      			$opacity = ''.number_format($opacity * 0.01 ,  2, '.', '');

	      		$opacity = str_replace('.00', '', $opacity);

	      		$color .= ',' . $opacity;

	      	}



	      	$color .= ')';



	      	return $color;

		}



		/**

		 * sanitize hex

		 * @since 5.3.1.6

		 */

		public static function sanitizeHex($hex){

			$hex = trim(str_replace('#', '' , $hex));

			if (strlen($hex) == 3) {

			    $hex[5] = $hex[2]; // f60##0

			    $hex[4] = $hex[2]; // f60#00

			    $hex[3] = $hex[1]; // f60600

			    $hex[2] = $hex[1]; // f66600

			    $hex[1] = $hex[0]; // ff6600

			}

			return '#'.$hex;

		}

		

		/**

		 * Save presets

		 * @since 5.3.2

		 */

		public static function save_color_presets($presets){

			update_option('tp_colorpicker_presets', $presets);

			return self::get_color_presets();

		}

		

		

		/**

		 * Load presets

		 * @since 5.3.2

		 */

		public static function get_color_presets(){

			return get_option('tp_colorpicker_presets', array());

		}

		

	}

}



?>