
#ifdef HAVE_CONFIG_H
#include "../../../ext_config.h"
#endif

#include <php.h>
#include "../../../php_ext.h"
#include "../../../ext.h"

#include <Zend/zend_operators.h>
#include <Zend/zend_exceptions.h>
#include <Zend/zend_interfaces.h>

#include "kernel/main.h"
#include "kernel/object.h"
#include "kernel/operators.h"
#include "kernel/memory.h"
#include "kernel/fcall.h"
#include "kernel/exception.h"
#include "kernel/array.h"


/**
 * This file is part of the Phalcon Framework.
 *
 * (c) Phalcon Team <team@phalcon.io>
 *
 * For the full copyright and license information, please view the LICENSE.txt
 * file that was distributed with this source code.
 */
/**
 * Supplies form element definitions from a PHP array.
 */
ZEPHIR_INIT_CLASS(Phalcon_Forms_Loader_ArrayLoader)
{
	ZEPHIR_REGISTER_CLASS(Phalcon\\Forms\\Loader, ArrayLoader, phalcon, forms_loader_arrayloader, phalcon_forms_loader_arrayloader_method_entry, 0);

	/**
	 * @var array
	 */
	zend_declare_property_null(phalcon_forms_loader_arrayloader_ce, SL("definitions"), ZEND_ACC_PROTECTED);
	zend_class_implements(phalcon_forms_loader_arrayloader_ce, 1, phalcon_contracts_forms_schema_ce);
	return SUCCESS;
}

/**
 * @param array $definitions
 */
PHP_METHOD(Phalcon_Forms_Loader_ArrayLoader, __construct)
{
	zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
	zval *definitions_param = NULL;
	zval definitions;
	zval *this_ptr = getThis();

	ZVAL_UNDEF(&definitions);
	static zend_string *_zephir_prop_0 = NULL;
	if (UNEXPECTED(!_zephir_prop_0)) {
		_zephir_prop_0 = zend_string_init("definitions", 11, 1);
	}

	ZEND_PARSE_PARAMETERS_START(1, 1)
		ZEPHIR_Z_PARAM_ARRAY(definitions, definitions_param)
	ZEND_PARSE_PARAMETERS_END();
	ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0);
	zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__);
	zephir_fetch_params(1, 1, 0, &definitions_param);
	zephir_get_arrval(&definitions, definitions_param);
	zephir_update_property_zval_cached(this_ptr, _zephir_prop_0, 800, &definitions);
	ZEPHIR_MM_RESTORE();
}

/**
 * @phpstan-return array<int, array<string, mixed>>
 * @throws Exception
 */
PHP_METHOD(Phalcon_Forms_Loader_ArrayLoader, load)
{
	zend_bool _7;
	zend_string *_3;
	zend_ulong _2;
	zval definition, index, _0, *_1, _6, _4$$3, _8$$4;
	zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
	zephir_fcall_cache_entry *_5 = NULL;
	zend_long ZEPHIR_LAST_CALL_STATUS;
	zval *this_ptr = getThis();

	ZVAL_UNDEF(&definition);
	ZVAL_UNDEF(&index);
	ZVAL_UNDEF(&_0);
	ZVAL_UNDEF(&_6);
	ZVAL_UNDEF(&_4$$3);
	ZVAL_UNDEF(&_8$$4);
	static zend_string *_zephir_prop_0 = NULL;
	if (UNEXPECTED(!_zephir_prop_0)) {
		_zephir_prop_0 = zend_string_init("definitions", 11, 1);
	}
	ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0);
	zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__);

	zephir_read_property_cached(&_0, this_ptr, _zephir_prop_0, 800, PH_NOISY_CC | PH_READONLY);
	zephir_is_iterable(&_0, 0, "phalcon/Forms/Loader/ArrayLoader.zep", 48);
	if (Z_TYPE_P(&_0) == IS_ARRAY) {
		ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(&_0), _2, _3, _1)
		{
			ZEPHIR_INIT_NVAR(&index);
			if (_3 != NULL) { 
				ZVAL_STR_COPY(&index, _3);
			} else {
				ZVAL_LONG(&index, _2);
			}
			ZEPHIR_INIT_NVAR(&definition);
			ZVAL_COPY(&definition, _1);
			ZVAL_LONG(&_4$$3, zephir_get_intval(&index));
			ZEPHIR_CALL_METHOD(NULL, this_ptr, "validatedefinition", &_5, 0, &definition, &_4$$3);
			zephir_check_call_status();
		} ZEND_HASH_FOREACH_END();
	} else {
		ZEPHIR_CALL_METHOD(NULL, &_0, "rewind", NULL, 0);
		zephir_check_call_status();
		_7 = 1;
		while (1) {
			if (_7) {
				_7 = 0;
			} else {
				ZEPHIR_CALL_METHOD(NULL, &_0, "next", NULL, 0);
				zephir_check_call_status();
			}
			ZEPHIR_CALL_METHOD(&_6, &_0, "valid", NULL, 0);
			zephir_check_call_status();
			if (!zend_is_true(&_6)) {
				break;
			}
			ZEPHIR_CALL_METHOD(&index, &_0, "key", NULL, 0);
			zephir_check_call_status();
			ZEPHIR_CALL_METHOD(&definition, &_0, "current", NULL, 0);
			zephir_check_call_status();
				ZVAL_LONG(&_8$$4, zephir_get_intval(&index));
				ZEPHIR_CALL_METHOD(NULL, this_ptr, "validatedefinition", &_5, 0, &definition, &_8$$4);
				zephir_check_call_status();
		}
	}
	ZEPHIR_INIT_NVAR(&definition);
	ZEPHIR_INIT_NVAR(&index);
	RETURN_MM_MEMBER_TYPED(getThis(), "definitions", IS_ARRAY);
}

/**
 * @param mixed $definition
 * @param int   $index
 *
 * @throws Exception
 */
PHP_METHOD(Phalcon_Forms_Loader_ArrayLoader, validateDefinition)
{
	zend_bool _2, _7;
	zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
	zend_long index, ZEPHIR_LAST_CALL_STATUS;
	zval *definition, definition_sub, *index_param = NULL, _0$$3, _1$$3, _3, _8, _4$$4, _5$$4, _6$$4, _9$$5, _10$$5, _11$$5;

	ZVAL_UNDEF(&definition_sub);
	ZVAL_UNDEF(&_0$$3);
	ZVAL_UNDEF(&_1$$3);
	ZVAL_UNDEF(&_3);
	ZVAL_UNDEF(&_8);
	ZVAL_UNDEF(&_4$$4);
	ZVAL_UNDEF(&_5$$4);
	ZVAL_UNDEF(&_6$$4);
	ZVAL_UNDEF(&_9$$5);
	ZVAL_UNDEF(&_10$$5);
	ZVAL_UNDEF(&_11$$5);
	ZEND_PARSE_PARAMETERS_START(2, 2)
		Z_PARAM_ZVAL(definition)
		Z_PARAM_LONG(index)
	ZEND_PARSE_PARAMETERS_END();
	ZEPHIR_METHOD_GLOBALS_PTR = pecalloc(1, sizeof(zephir_method_globals), 0);
	zephir_memory_grow_stack(ZEPHIR_METHOD_GLOBALS_PTR, __func__);
	zephir_fetch_params(1, 2, 0, &definition, &index_param);
	if (Z_TYPE_P(definition) != IS_ARRAY) {
		ZEPHIR_INIT_VAR(&_0$$3);
		object_init_ex(&_0$$3, phalcon_forms_exceptions_schemaentrynotarray_ce);
		ZVAL_LONG(&_1$$3, index);
		ZEPHIR_CALL_METHOD(NULL, &_0$$3, "__construct", NULL, 0, &_1$$3);
		zephir_check_call_status();
		zephir_throw_exception_debug(&_0$$3, "phalcon/Forms/Loader/ArrayLoader.zep", 60);
		ZEPHIR_MM_RESTORE();
		return;
	}
	_2 = !(zephir_array_isset_value_string(definition, SL("type")));
	if (!(_2)) {
		zephir_array_fetch_string(&_3, definition, SL("type"), PH_NOISY | PH_READONLY, "phalcon/Forms/Loader/ArrayLoader.zep", 63);
		_2 = ZEPHIR_IS_EMPTY(&_3);
	}
	if (_2) {
		ZEPHIR_INIT_VAR(&_4$$4);
		object_init_ex(&_4$$4, phalcon_forms_exceptions_schemaentrymissingkey_ce);
		ZVAL_LONG(&_5$$4, index);
		ZEPHIR_INIT_VAR(&_6$$4);
		ZVAL_STRING(&_6$$4, "type");
		ZEPHIR_CALL_METHOD(NULL, &_4$$4, "__construct", NULL, 0, &_5$$4, &_6$$4);
		zephir_check_call_status();
		zephir_throw_exception_debug(&_4$$4, "phalcon/Forms/Loader/ArrayLoader.zep", 64);
		ZEPHIR_MM_RESTORE();
		return;
	}
	_7 = !(zephir_array_isset_value_string(definition, SL("name")));
	if (!(_7)) {
		zephir_array_fetch_string(&_8, definition, SL("name"), PH_NOISY | PH_READONLY, "phalcon/Forms/Loader/ArrayLoader.zep", 67);
		_7 = ZEPHIR_IS_EMPTY(&_8);
	}
	if (_7) {
		ZEPHIR_INIT_VAR(&_9$$5);
		object_init_ex(&_9$$5, phalcon_forms_exceptions_schemaentrymissingkey_ce);
		ZVAL_LONG(&_10$$5, index);
		ZEPHIR_INIT_VAR(&_11$$5);
		ZVAL_STRING(&_11$$5, "name");
		ZEPHIR_CALL_METHOD(NULL, &_9$$5, "__construct", NULL, 0, &_10$$5, &_11$$5);
		zephir_check_call_status();
		zephir_throw_exception_debug(&_9$$5, "phalcon/Forms/Loader/ArrayLoader.zep", 68);
		ZEPHIR_MM_RESTORE();
		return;
	}
	ZEPHIR_MM_RESTORE();
}

