
#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/array.h"
#include "kernel/memory.h"
#include "kernel/operators.h"
#include "kernel/fcall.h"
#include "kernel/concat.h"
#include "kernel/string.h"


/**
 * Phalcon\Version
 *
 * This class allows to get the installed version of the framework
 */
ZEPHIR_INIT_CLASS(Phalcon_Version) {

	ZEPHIR_REGISTER_CLASS(Phalcon, Version, phalcon, version, phalcon_version_method_entry, 0);

	/**
	 * The constant referencing the major version. Returns 0
	 *
	 * <code>
	 * echo Phalcon\Version::getPart(
	 *     Phalcon\Version::VERSION_MAJOR
	 * );
	 * </code>
	 */
	zend_declare_class_constant_long(phalcon_version_ce, SL("VERSION_MAJOR"), 0 TSRMLS_CC);

	/**
	 * The constant referencing the major version. Returns 1
	 *
	 * <code>
	 * echo Phalcon\Version::getPart(
	 *     Phalcon\Version::VERSION_MEDIUM
	 * );
	 * </code>
	 */
	zend_declare_class_constant_long(phalcon_version_ce, SL("VERSION_MEDIUM"), 1 TSRMLS_CC);

	/**
	 * The constant referencing the major version. Returns 2
	 *
	 * <code>
	 * echo Phalcon\Version::getPart(
	 *     Phalcon\Version::VERSION_MINOR
	 * );
	 * </code>
	 */
	zend_declare_class_constant_long(phalcon_version_ce, SL("VERSION_MINOR"), 2 TSRMLS_CC);

	/**
	 * The constant referencing the major version. Returns 3
	 *
	 * <code>
	 * echo Phalcon\Version::getPart(
	 *     Phalcon\Version::VERSION_SPECIAL
	 * );
	 * </code>
	 */
	zend_declare_class_constant_long(phalcon_version_ce, SL("VERSION_SPECIAL"), 3 TSRMLS_CC);

	/**
	 * The constant referencing the major version. Returns 4
	 *
	 * <code>
	 * echo Phalcon\Version::getPart(
	 *     Phalcon\Version::VERSION_SPECIAL_NUMBER
	 * );
	 * </code>
	 */
	zend_declare_class_constant_long(phalcon_version_ce, SL("VERSION_SPECIAL_NUMBER"), 4 TSRMLS_CC);

	return SUCCESS;

}

/**
 * Area where the version number is set. The format is as follows:
 * ABBCCDE
 *
 * A - Major version
 * B - Med version (two digits)
 * C - Min version (two digits)
 * D - Special release: 1 = Alpha, 2 = Beta, 3 = RC, 4 = Stable
 * E - Special release version i.e. RC1, Beta2 etc.
 */
PHP_METHOD(Phalcon_Version, _getVersion) {

	zval *_0 = NULL;

	ZEPHIR_MM_GROW();

	zephir_create_array(return_value, 5, 0 TSRMLS_CC);
	ZEPHIR_INIT_VAR(_0);
	ZVAL_LONG(_0, 3);
	zephir_array_fast_append(return_value, _0);
	ZEPHIR_INIT_NVAR(_0);
	ZVAL_LONG(_0, 4);
	zephir_array_fast_append(return_value, _0);
	ZEPHIR_INIT_NVAR(_0);
	ZVAL_LONG(_0, 0);
	zephir_array_fast_append(return_value, _0);
	ZEPHIR_INIT_NVAR(_0);
	ZVAL_LONG(_0, 4);
	zephir_array_fast_append(return_value, _0);
	ZEPHIR_INIT_NVAR(_0);
	ZVAL_LONG(_0, 0);
	zephir_array_fast_append(return_value, _0);
	RETURN_MM();

}

/**
 * Translates a number to a special release
 *
 * If Special release = 1 this function will return ALPHA
 */
PHP_METHOD(Phalcon_Version, _getSpecial) {

	zval *special_param = NULL, *suffix = NULL;
	zend_long special;

	ZEPHIR_MM_GROW();
	zephir_fetch_params(1, 1, 0, &special_param);

	special = zephir_get_intval(special_param);


	ZEPHIR_INIT_VAR(suffix);
	ZVAL_STRING(suffix, "", 1);
	do {
		if (special == 1) {
			ZEPHIR_INIT_NVAR(suffix);
			ZVAL_STRING(suffix, "ALPHA", 1);
			break;
		}
		if (special == 2) {
			ZEPHIR_INIT_NVAR(suffix);
			ZVAL_STRING(suffix, "BETA", 1);
			break;
		}
		if (special == 3) {
			ZEPHIR_INIT_NVAR(suffix);
			ZVAL_STRING(suffix, "RC", 1);
			break;
		}
	} while(0);

	RETURN_CCTOR(suffix);

}

/**
 * Returns the active version (string)
 *
 * <code>
 * echo Phalcon\Version::get();
 * </code>
 */
PHP_METHOD(Phalcon_Version, get) {

	zval *version = NULL, *major = NULL, *medium = NULL, *minor = NULL, *special = NULL, *specialNumber = NULL, *result = NULL, *suffix = NULL, *_1$$3;
	zephir_fcall_cache_entry *_0 = NULL;
	zend_long ZEPHIR_LAST_CALL_STATUS;

	ZEPHIR_MM_GROW();

	ZEPHIR_CALL_STATIC(&version, "_getversion", NULL, 0);
	zephir_check_call_status();
	ZEPHIR_OBS_VAR(major);
	zephir_array_fetch_long(&major, version, 0, PH_NOISY, "phalcon/version.zep", 139 TSRMLS_CC);
	ZEPHIR_OBS_VAR(medium);
	zephir_array_fetch_long(&medium, version, 1, PH_NOISY, "phalcon/version.zep", 140 TSRMLS_CC);
	ZEPHIR_OBS_VAR(minor);
	zephir_array_fetch_long(&minor, version, 2, PH_NOISY, "phalcon/version.zep", 141 TSRMLS_CC);
	ZEPHIR_OBS_VAR(special);
	zephir_array_fetch_long(&special, version, 3, PH_NOISY, "phalcon/version.zep", 142 TSRMLS_CC);
	ZEPHIR_OBS_VAR(specialNumber);
	zephir_array_fetch_long(&specialNumber, version, 4, PH_NOISY, "phalcon/version.zep", 143 TSRMLS_CC);
	ZEPHIR_INIT_VAR(result);
	ZEPHIR_CONCAT_VSVSVS(result, major, ".", medium, ".", minor, " ");
	ZEPHIR_CALL_STATIC(&suffix, "_getspecial", &_0, 485, special);
	zephir_check_call_status();
	if (!ZEPHIR_IS_STRING(suffix, "")) {
		ZEPHIR_INIT_VAR(_1$$3);
		ZEPHIR_CONCAT_VSV(_1$$3, suffix, " ", specialNumber);
		zephir_concat_self(&result, _1$$3 TSRMLS_CC);
	}
	zephir_fast_trim(return_value, result, NULL , ZEPHIR_TRIM_BOTH TSRMLS_CC);
	RETURN_MM();

}

/**
 * Returns the numeric active version
 *
 * <code>
 * echo Phalcon\Version::getId();
 * </code>
 */
PHP_METHOD(Phalcon_Version, getId) {

	zval *version = NULL, *major = NULL, *medium = NULL, *minor = NULL, *special = NULL, *specialNumber = NULL, _0 = zval_used_for_init, *_1 = NULL, *_2 = NULL;
	zend_long ZEPHIR_LAST_CALL_STATUS;

	ZEPHIR_MM_GROW();

	ZEPHIR_CALL_STATIC(&version, "_getversion", NULL, 0);
	zephir_check_call_status();
	ZEPHIR_OBS_VAR(major);
	zephir_array_fetch_long(&major, version, 0, PH_NOISY, "phalcon/version.zep", 169 TSRMLS_CC);
	ZEPHIR_OBS_VAR(medium);
	zephir_array_fetch_long(&medium, version, 1, PH_NOISY, "phalcon/version.zep", 170 TSRMLS_CC);
	ZEPHIR_OBS_VAR(minor);
	zephir_array_fetch_long(&minor, version, 2, PH_NOISY, "phalcon/version.zep", 171 TSRMLS_CC);
	ZEPHIR_OBS_VAR(special);
	zephir_array_fetch_long(&special, version, 3, PH_NOISY, "phalcon/version.zep", 172 TSRMLS_CC);
	ZEPHIR_OBS_VAR(specialNumber);
	zephir_array_fetch_long(&specialNumber, version, 4, PH_NOISY, "phalcon/version.zep", 173 TSRMLS_CC);
	ZEPHIR_SINIT_VAR(_0);
	ZVAL_STRING(&_0, "%02s", 0);
	ZEPHIR_CALL_FUNCTION(&_1, "sprintf", NULL, 164, &_0, medium);
	zephir_check_call_status();
	ZEPHIR_SINIT_NVAR(_0);
	ZVAL_STRING(&_0, "%02s", 0);
	ZEPHIR_CALL_FUNCTION(&_2, "sprintf", NULL, 164, &_0, minor);
	zephir_check_call_status();
	ZEPHIR_CONCAT_VVVVV(return_value, major, _1, _2, special, specialNumber);
	RETURN_MM();

}

/**
 * Returns a specific part of the version. If the wrong parameter is passed
 * it will return the full version
 *
 * <code>
 * echo Phalcon\Version::getPart(
 *     Phalcon\Version::VERSION_MAJOR
 * );
 * </code>
 */
PHP_METHOD(Phalcon_Version, getPart) {

	zephir_fcall_cache_entry *_0 = NULL;
	zval *part_param = NULL, *version = NULL, *result = NULL, *_1$$4;
	zend_long part, ZEPHIR_LAST_CALL_STATUS;

	ZEPHIR_MM_GROW();
	zephir_fetch_params(1, 1, 0, &part_param);

	part = zephir_get_intval(part_param);


	ZEPHIR_CALL_STATIC(&version, "_getversion", NULL, 0);
	zephir_check_call_status();
	do {
		if (part == 0 || part == 1 || part == 2 || part == 4) {
			ZEPHIR_OBS_VAR(result);
			zephir_array_fetch_long(&result, version, part, PH_NOISY, "phalcon/version.zep", 200 TSRMLS_CC);
			break;
		}
		if (part == 3) {
			zephir_array_fetch_long(&_1$$4, version, 3, PH_NOISY | PH_READONLY, "phalcon/version.zep", 204 TSRMLS_CC);
			ZEPHIR_CALL_STATIC(&result, "_getspecial", &_0, 485, _1$$4);
			zephir_check_call_status();
			break;
		}
		ZEPHIR_CALL_STATIC(&result, "get", NULL, 0);
		zephir_check_call_status();
		break;
	} while(0);

	RETURN_CCTOR(result);

}

