<?php namespace ProcessWire;

/**
 * ProcessWire Float Fieldtype
 *
 * Field that stores a floating point number. 
 *
 * For documentation about the fields used in this class, please see:  
 * /wire/core/Fieldtype.php
 * 
 * ProcessWire 3.x, Copyright 2016 by Ryan Cramer
 * https://processwire.com
 *
 */

class FieldtypeFloat extends Fieldtype {

	public static function getModuleInfo() {
		return array(
			'title' => __('Float', __FILE__),
			'summary' => __('Field that stores a floating point (decimal) number', __FILE__),
			'version' => 105,
			'permanent' => true, 
			);
	}

	public function ___getCompatibleFieldtypes(Field $field) {
		$fieldtypes = parent::___getCompatibleFieldtypes($field); 
		foreach($fieldtypes as $type) {
			if(	!$type instanceof FieldtypeInteger && 
				!$type instanceof FieldtypeFloat &&
				$type != 'FieldtypeText') {

				$fieldtypes->remove($type); 
			}
		}
		return $fieldtypes; 
	}

	public function getBlankValue(Page $page, Field $field) {
		return ''; 
	}

	public function isEmptyValue(Field $field, $value) {
		if(($value === "0" || $value === 0 || $value === "0.0" || $value === 0.0) && $field->zeroNotEmpty) {
			// when zeroNotEmpty option is set, we don't count a literal "0" is being a blank value
			return false;
		}
		return empty($value);
	}

	public function sanitizeValue(Page $page, Field $field, $value) {
		if(!strlen("$value")) return '';
		if(!is_float($value) && !is_int($value)) {
			$value = $this->wire('sanitizer')->float((string) $value, array('blankValue' => ''));
		}
		if(is_null($field->precision)) {
			$value = (float) $value;
		} else {
			$value = round((float) $value, $field->precision);
		}
		return $value; 
	}

	/*
	public function formatValue(Page $page, Field $field, $value) {
		// @todo add support for number_format options
		return $value; 	
	}
	*/

	public function getInputfield(Page $page, Field $field) {
		$inputfield = $this->modules->get('InputfieldFloat'); 
		$inputfield->class = $this->className();
		$inputfield->precision = $field->precision; 
		return $inputfield; 
	}

	public function ___sleepValue(Page $page, Field $field, $value) {
		$precision = $field->precision; 
		if(is_null($precision)) $precision = self::getPrecision($value); 
		if(!is_string($value)) $value = number_format($value, $precision, '.', '');

		/*

		// handle commas vs. dots issue with other locales
		$info = localeconv();

		if(!empty($info['mon_thousands_sep'])) {
			if(strpos($value, $info["mon_thousands_sep"]) !== false) {
				$value = str_replace($info["mon_thousands_sep"] , "", $value);
			}
		}

		if(!empty($info['mon_decimal_point'])) { 
			if($info["mon_decimal_point"] !== '.' && strpos($value, $info["mon_decimal_point"]) !== false) {
				$value = str_replace($info["mon_decimal_point"] , ".", $value);
			}
		}

		$value = floatval($value); 
		*/
		return $value; 
	}
	
	public static function getPrecision($value) {
		$remainder = ceil($value) - $value;
		$precision = strlen(ltrim($remainder, '0., '));
		if(!$precision) $precision = 1; 
		return $precision;
	}

	public function getDatabaseSchema(Field $field) {
		$schema = parent::getDatabaseSchema($field); 
		$schema['data'] = 'float NOT NULL';
		return $schema;
	}

	public function ___getConfigInputfields(Field $field) {
		$inputfields = parent::___getConfigInputfields($field);

		if(is_null($field->precision)) $field->precision = 2; 

		$f = $this->modules->get('InputfieldInteger');
		$f->attr('name', 'precision'); 
		$f->label = $this->_('Number of decimal digits to round to');
		$f->attr('value', $field->precision); 
		$f->attr('size', 8); 
		$inputfields->append($f);
		
		$f = $this->wire('modules')->get('FieldtypeInteger')->___getConfigInputfields($field)->getChildByName('zeroNotEmpty'); 
		if($f) $inputfields->add($f); 

		return $inputfields; 
	}

	/*
	public function getMatchQuery($query, $table, $subfield, $operator, $value) {
		if(!is_int($value) && !is_float($value)) {
			$value = self::strToFloat((string) $value);
		}
		return parent::getMatchQuery($query, $table, $subfield, $operator, $value); 
	}
	*/

	/**
	 * Convert float string with commas to float value
	 * 
	 * Most based on: http://php.net/manual/en/function.floatval.php#114486
	 * 
	 * @param string $str
	 * @return float|string
	 * @deprecated
	 * 
	 */
	public static function strToFloat($str) { 
		return wire('sanitizer')->float($str, array('blankValue' => ''));
	}

}

