<?php
/**
 * Please see weepie-framework.php for more details.
 */

namespace WpieFw\Helpers;

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

/**
 * WpieSettingsHelper class - helper class for setting tasks
 *
 * @author $Author: Vincent Weber <weepie-plugins@outlook.com>$
 */
final class WpieSettingsHelper
{
	/**
	 * Check if current field is a WordPress specific field
	 *
	 * @param array $field
	 * @return boolean
	 */
	public static function isWpField( $field )
	{
		return( false === strpos( $field['elem'], 'wp' ) ) ? false : true;
	}


	/**
	 * Check if current settingsfield is a form group based on field name
	 *
	 * Groups are indicated in the formfields array like 'group-0', 'group-1' etc.
	 * The purpose is to create setting sections within a settings tab
	 *
	 * @param string $fieldName
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isFormGroup( $fieldName )
	{
		return ( 'group' === $fieldName );
	}

	/**
	 * Check if current settingsfield is a form field based on field name
	 *
	 * @param string $fieldName
	 * @return boolean
	 */
	public static function isFormField( $fieldName )
	{
		return ( 'field' === $fieldName );
	}

	/**
	 * Check if current settingsfield is a formgroup meta entry
	 *
	 * @param string $fieldName
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isFormGroupMeta( $fieldName )
	{
		return ( 'group_title' === $fieldName ||  'group_descr' === $fieldName ||  'group_warning' === $fieldName || 'group_notice' === $fieldName ) ? true : false;
	}


	/**
	 * Check if current settingsfield is an input type text
	 *
	 * @param array $field
	 *
	 * @since 1.2
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isText( array $field )
	{
		return ( 'text' === $field['elem'] );
	}


	/**
	 * Check if current settingsfield is a colorpicker
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isColorPicker( $field )
	{
		return ( 'color' === $field['elem'] || 'colorpicker' === $field['elem'] ) ? true : false;
	}


	/**
	 * Check if current settingsfield is a <select>
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isSelect( $field )
	{
		return ( 'select' === $field['elem'] );
	}


	/**
	 * Check if current settingsfield is a checkbox
	 *
	 * @param array $field
	 *
	 * @since 1.2
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isCheckbox( $field )
	{
		return ( 'checkbox' === $field['elem'] );
	}


	/**
	 * Check if current settingsfield is a multi checkbox
	 *
	 * @param array $field
	 *
	 * @since 1.1.8
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isCheckboxmulti( $field )
	{
		return ( 'checkboxmulti' === $field['elem'] );
	}


	/**
	 * Check if current settingsfield is a multi options element
	 *
	 * possible elements are:select, checkboxmulti
	 *
	 * @param array $field
	 *
	 * @since 1.1.8
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isMultiElement( $field )
	{
		if( self::isSelect( $field ) ) {
			return true;
		} elseif( self::isCheckboxmulti( $field ) ) {
			return true;
		} else {
			return false;
		}
	}


	/**
	 * Check if current settingsfield is a <textarea>
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isTextarea( $field )
	{
		return ( 'textarea' === $field['elem'] );
	}


	/**
	 * Check if current settingsfield is a WP <textarea>
	 *
	 * @param array $field
	 *
	 * @since 1.2
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isWpTextarea( $field )
	{
		return ( 'wptextarea' === $field['elem'] || 'wptextareabasic' === $field['elem'] );
	}

	/**
	 * Check if current settingsfield is a WP Custom Post Type list
	 *
	 * @param array $field
	 *
	 * @since 1.3
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isWpPostTypeList( $field )
	{
		return ( 'wpcpostlist' === $field['elem'] || 'wpcpostlist_edit' === $field['elem'] );
	}


	/**
	 * Check if current settingsfield is a external template
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isTemplate( $field )
	{
		return ( isset( $field['inner'] ) &&
				 isset( $field['inner']['@attributes'] ) &&
				 isset( $field['inner']['@attributes']['template'] ) &&
				'true' === $field['inner']['@attributes']['template'] ) ? true : false;
	}


	/**
	 * Check if curren field is a disabled or hidden element
	 *
	 * @param array $field
	 *
	 * @since 1.0
	 *
	 * @return bool true if yes and false if no
	 */
	public static function isHiddenOrDisabled( $field )
	{
		return ( self::isDisabled( $field ) || self::isHidden( $field ) ) ? true : false;
	}


	/**
	 * Check if current field is a disabled element
	 *
	 * @param array $field
	 *
	 * @since 1.0
	 *
	 * @return bool
	 */
	public static function isDisabled( $field )
	{
		return ( 'disabled' === $field['elem'] ) ? true : false;
	}


	/**
	 * Check if curren field is a hidden element
	 *
	 * @param array $field
	 *
	 * @since 1.0
	 *
	 * @return bool
	 */
	public static function isHidden( $field )
	{
		return ( 'hidden' === $field['elem'] ) ? true : false;
	}


	/**
	 * Check if current field is has type attribute for numeric
	 *
	 * @param array $field
	 *
	 * @since 1.2
	 *
	 * @return bool
	 */
	public static function isNumeric( $field )
	{
		return ( $field['type'] && 'numeric' === $field['type'] );
	}


	/**
	 * Check if current field is has type attribute for numeric absolute
	 *
	 * @param array $field
	 *
	 * @since 1.2
	 *
	 * @return bool
	 */
	public static function isNumericAbs( $field )
	{
		return ( $field['type'] && 'numeric_abs' === $field['type'] );
	}

	/**
	 * Check if current field is custom post type list with _click_select true
	 *
	 * @param array $field
	 *
	 * @uses self::hasAttrNameValue()
	 *
	 * @since 1.3.1
	 *
	 * @return bool
	 */
	public static function isClickSelect( $field )
	{
		return self::hasAttrNameValue( $field, '_click_select', 'value', 'true' );
	}

	/**
	 * Check if passed setting has the default flag
	 *
	 * Attribute is set to true: <settings default="true|1">
	 *
	 * @param array $settings
	 *
	 * @since 1.2
	 *
	 * @return bool
	 */
	public static function isDefaultSetting( $settings )
	{
		return ( isset( $settings['@attributes'] ) && isset( $settings['@attributes']['default'] ) && ( 'true' === $settings['@attributes']['default'] || '1' === $settings['@attributes']['default'] ) );
	}


	/**
	 * Check if field needs sanitizing
	 *
	 * SKIP: checkbox, select, wptextarea, wptextareabasic
	 *
	 * @param array $field
	 *
	 * @since 1.2
	 *
	 * @return bool
	 */
	public static function isFieldToSanitize( $field )
	{
		if( self::isCheckbox( $field ) )
			return false;
		elseif( self::isSelect( $field ) )
			return false;
		elseif( self::isWpTextarea( $field ) )
			return false;
		else
			return true;
	}

	/**
	 * Check if current form field/group has a name attribute
	 *
	 * @param array $field
	 *
	 * @since 1.3.3
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasAttributeName( $field )
	{
		return ( isset($field['@attributes']['name']) && '' !== $field['@attributes']['name'] ) ? true : false;
	}

	/**
	 * Check if current settingsfield has a formgroup title
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasFormGroupTitle( $field )
	{
		return ( isset( $field['group_title'] ) && '' !== $field['group_title'] ) ? true : false;
	}

	/**
	 * Check if current settingsfield has a formgroup description
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasFormGroupDescr( $field )
	{
		return ( isset( $field['group_descr'] ) && '' !== $field['group_descr'] ) ? true : false;
	}

	/**
	 * Check if current settingsfield has a formgroup warning
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasFormGroupWarning( $field )
	{
		return ( isset( $field['group_warning'] ) && '' !== $field['group_warning'] ) ? true : false;
	}

	/**
	 * Check if current settingsfield has a formgroup notice
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasFormGroupNotice( $field )
	{
		return ( isset( $field['group_notice'] ) && '' !== $field['group_notice'] ) ? true : false;
	}

	/**
	 * Check if current settingsfield has a description
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasDescr( $field )
	{
		return ( isset($field['descr']) && '' !== $field['descr'] ) ? true : false;
	}

	/**
	 * Check if current settingsfield has HTML attributes
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasAttr( $field )
	{
		return ( isset( $field['attributes'] ) && isset( $field['attributes']['attr'] ) ) ? true : false;
	}

	/**
	 * Check if field has attributes
	 *
	 * @param array $field
	 *
	 * @since 1.4.x
	 */
	public static function hasFieldAttr( array $field )
	{
		return ( isset( $field['@attributes'] ) );
	}

	/**
	 * Check if current settingsfield has an attribute with given value
	 *
	 * @param array $field
	 * @param string $nameAttr
	 * @param string $nameValue
	 * @param string $valueValue
	 *
	 * @since 1.0
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasAttrNameValue( $field, $nameAttr, $nameValue, $valueValue )
	{
		if( isset( $field['attributes'] ) ) {
			foreach ( $field['attributes']['attr'] as $at ) {
				if( isset( $at['@attributes'] ) && isset( $at['@attributes']['name'] ) && isset( $at['@attributes'][$nameValue] ) ) {
					return ( $nameAttr === $at['@attributes']['name'] && $valueValue === $at['@attributes'][$nameValue] );

				} elseif( isset( $at['name'] ) && isset( $at[$nameValue] ) ) {
					return ( $nameAttr === $at['name'] && $valueValue === $at[$nameValue] );
				}
			}
		}
		return false;
	}


	/**
	 * Check if current settingsfield has selectbox options
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasSelectOptions( $field )
	{
		return ( isset( $field['options'] ) && isset( $field['options']['option'] ) );
	}


	/**
	 * Check if current settingsfield has multi checkbox check boxes
	 *
	 * @param array $field
	 *
	 * @since 1.1.8
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasMultiCheckbox( $field )
	{
		return ( isset($field['check']) && isset($field['check']['box']) );
	}


	/**
	 * Check if current settingsfield has innerHTml
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasInnerHtml( $field )
	{
		return ( isset($field['inner']) && '' !== $field['inner'] ) ? true : false;
	}

	/**
	 * Check if current settingsfield has a title
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasTitle( $field )
	{
		return ( isset($field['title']) && '' !== $field['title'] ) ? true : false;
	}


	/** Check if current field has a default value
	 *
	 * @param array $field
	 *
	 * @since 1.0
	 *
	 * @return bool true if yes and false if no
	 */
	public static function hasDefault( $field )
	{
		return ( isset($field['default']) && '' !== $field['default'] ) ? true : false;
	}

	/**
	 * Get array with all field entries indexed by field name attribute
	 *
	 * @param array $settings
	 *
	 * @uses self::getFieldAttributeName()
	 *
	 * @return array
	 */
	public static function getFields( array $settings )
	{
		if( isset( $settings['settings'] ) ) {
			$settings = $settings['settings'];
		}

		$fields = [];
		foreach ( $settings as $fieldName => $fieldData ) {
			if( self::isFormGroup( $fieldName ) ) {
				foreach( $fieldData as $data ) {
					// correct for single field arrays
					// single field arrays are not inside an array
					if( !isset( $data['field'][0] ) ) {
						$data['field'] = [ $data['field'] ];
					}

					foreach ( $data['field'] as $field ) {
						$name = self::getFieldAttributeName( $field );
						if( '' !== $name ) {
							$fields[$name] = $field;
						}
					}
				}
			} elseif( self::isFormField( $fieldName ) ) {
				foreach( $fieldData as $field ) {
					$name = self::getFieldAttributeName( $field );
					if( '' !== $name ) {
						$fields[$name] = $field;
					}
				}
			}
		}

		return $fields;
	}

	/**
	 * Get field names from settings array
	 *
	 * @param array $settings
	 *
	 * @since 2.0
	 *
	 * @return array
	 */
	public static function getFieldNames( array $settings = [] )
	{
		if( !isset( $settings['settings'] ) ) {
			return [];
		}

		return array_keys( self::getFields( $settings ) );
	}

	/**
	 * Get array with fields that needs validation
	 *
	 * Field should have attribute like <field validate="y">
	 *
	 * @param array $fields
	 *
	 * @since 1.1.x
	 *
	 * @return array with fields indexed by field name
	 */
	public static function getFieldsToValidate( array $fields )
	{
		$validate = [];
		foreach( $fields as $name => $field ) {
			if( isset( $field['@attributes'] ) && isset( $field['@attributes']['validate'] ) && 'y' === $field['@attributes']['validate'] ) {
				$validate[$name] = $field;
			}
		}

		return $validate;
	}


	/**
	 * Get formfield attributes
	 *
	 * If the field is a colorpicker input, a class 'colorinput' is added
	 * For div elements 'name' and 'value' are not applied
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return array
	 */
	public static function getAttr( $field )
	{
		//TODO: loop threw attributes? Now only HTML 'class' attribute can be set from formfields array in BaseForm child classes
		$attributes = [];

		if( self::hasAttr($field) ) {
			foreach( $field['attributes']['attr'] as $at ) {
				if( isset( $at['@attributes'] ) && isset( $at['@attributes']['name'] ) && isset( $at['@attributes']['value'] ) ) {
					$attributes[$at['@attributes']['name']] = $at['@attributes']['value'];
				} elseif( isset( $at['name'] ) && isset( $at['value'] ) ) {
					$attributes[$at['name']] = $at['value'];
				}
			}
		}

		return $attributes;
	}

	/**
	 * Get all field attributes
	 *
	 * @param array $field
	 *
	 * @since 1.4.x
	 *
	 * @return array
	 */
	public static function getFieldAttr( array $field )
	{
		$attributes = [];

		if( self::hasFieldAttr( $field ) ) {
			foreach( $field['@attributes'] as $name => $value ) {
				if( '' !== ( $val = trim( $value ) ) ) {
					$attributes[$name] = $val;
				}
			}
		}

		return $attributes;
	}

	/**
	 * Get selectbox options
	 *
	 * @param array $field
	 *
	 * @since 0.1
	 *
	 * @return array or empty array
	 */
	public static function getSelectOptions( $field )
	{
		$options = [];

		if( self::hasSelectOptions( $field ) )
		{
			foreach ( $field['options']['option'] as $option )
			{
				$options[$option['@attributes']['id']] = trim( $option['_value'] );
			}
		}

		return $options;
	}


	/**
	 * Get multi checkbox options
	 *
	 * @param array $field
	 *
	 * @since 1.1.8
	 *
	 * @return array or empty array
	 */
	public static function getCheckboxOptions( $field )
	{
		$checkboxes = [];

		if( self::hasMultiCheckbox( $field ) )
		{
			foreach ( $field['check']['box'] as $box )
			{
				$checkboxes[$box['@attributes']['id']] = trim( $box['_value'] );
			}
		}

		return $checkboxes;
	}


	/**
	 * Get options for a multi field
	 *
	 * @param array $field
	 *
	 * @uses self::getSelectOptions()
	 * @uses self::getCheckboxOptions()
	 *
	 * @since 1.1.8
	 *
	 * @return array or empty array
	 */
	public static function getMultiOptions( $field  )
	{
		if( self::isSelect( $field ) )
		{
			return self::getSelectOptions( $field );
		}
		elseif( self::isCheckboxmulti( $field ) )
		{
			return self::getCheckboxOptions( $field );
		}
		else {
			return [];
		}
	}


	/**
	 * Get InnerHtml
	 *
	 * @param array $field
	 * @param string $modulePath optional
	 * @param array $vars optional
	 *
	 * @since 0.1
	 *
	 * @return string or empty string
	 */
	public static function getInnerHtml( $field, $modulePath = '', $vars = [] )
	{
		$innerHtml = '';

		if( self::hasInnerHtml($field) && self::isTemplate($field) ) {
			$file = $modulePath . DIRECTORY_SEPARATOR . $field['inner']['_value'];

			if( file_exists( $file ) ) {

				$fileName = basename( $file );
				$basePath = dirname( $file );

				try {
					$finder = new \WpieFw\Templates\Files\WpieTemplatesFileFinder( $basePath, '', '', $fileName, false );
					$template =  new \WpieFw\Templates\WpieTemplate( $finder, $field['@attributes']['name']);
				} catch( \WpieFw\Exceptions\WpieExceptionInterface $e ) {
					return $e->getMessage();
				}

				$template->setVars( $vars );
				$innerHtml = $template->render(false, true);

				unset($template, $vars);

			} else {
				$innerHtml = __( sprintf( 'Template file "%s" is not a valid file path.', $file ), 'weepie' );
			}

		} elseif ( self::hasInnerHtml( $field ) && !self::isTemplate( $field ) ) {

			$innerHtml = $field['inner'];

		} else {

			//$innerHtml = '';
		}

		return  $innerHtml;
	}

	/**
	 * Get setting priority
	 *
	 * @access public
	 *
	 * @param array $settings
	 *
	 * @since 1.2
	 *
	 * @return int or bool false if no prio is found
	 */
	public static function getSettingPriority( $settings )
	{
		return ( isset( $settings['prio'] ) && ( is_int( (int)$settings['prio'] ) ) ) ? (int)$settings['prio'] : false;
	}

	/**
	 * Get a formgroup name attribute
	 *
	 * @param array $field
	 *
	 * @since 1.3.3
	 *
	 * @return string
	 */
	public static function getFieldAttributeName( $field )
	{
		if( self::hasAttributeName( $field ) ) {
			return $field['@attributes']['name'];
		} else {
			return '';
		}
	}

	/**
	 * Get a CSS id attribute string based on field name
	 *
	 * @param array $field
	 *
	 * @since 1.3.3
	 *
	 * @return string
	 */
	public static function getFieldCssIdString( $type, $field )
	{
		$str = '';
		if( self::hasAttributeName( $field ) ) {
			$AttributeNameNice = str_replace( '_', '-', self::getFieldAttributeName( $field ) ) ;
			$str = sprintf( ' id="form-%s-%s"', $type, $AttributeNameNice );
		}

		return $str;
	}
}