<?php
/*
** Zabbix
** Copyright (C) 2001-2014 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/

/**
 * Class containing methods for operations Value Mapping.
 *
 * @package API
 */
class CValuemapping extends CZBXAPI {
	protected $tableName = 'valuemaps';
	protected $tableAlias = 'vm';
	protected $sortColumns = array (
			'valuemapid' 
	);

	/**
	 * Get Value Mapping data
	 *
	 * @param array $options
	 * @param array $options['valuemapids'] filter by ValueMapping IDs
	 * @param string $options['name'] filter by Name of ValueMapping
	 * @param boolean $options['output'] output only Mediatype IDs if not set.
	 * @param boolean $options['count'] output only count of objects in result. ( result returned in property 'rowscount' )
	 * @param string $options['pattern'] filter by Host name containing only give pattern
	 * @param int $options['limit'] output will be limited to given number
	 * @param string $options['sortfield'] output will be sorted by given property [ 'valuemapid', 'name' ]
	 * @param string $options['sortorder'] output will be sorted in given order [ 'ASC', 'DESC' ]
	 * @return array
	 */
	public function get($options = array()) {
		$result = array ();
		$nodeCheck = false;
		$userType = self::$userData ['type'];
		
		$sqlParts = array (
				'select' => array (
						'valuemaps' => 'vm.valuemapid' 
				),
				'from' => array (
						'valuemaps' => 'valuemaps vm' 
				),
				'where' => array (),
				'group' => array (),
				'order' => array (),
				'limit' => null 
		);
		
		$defOptions = array (
				'valuemapids' => null,
				'name' => null,
				'with_mappings' => null,
				'editable' => null,
				// filter
				'filter' => null,
				'search' => null,
				'searchByAny' => null,
				'startSearch' => null,
				'excludeSearch' => null,
				'searchWildcardsEnabled' => null,
				// output
				'output' => API_OUTPUT_REFER,
				'selectUsers' => null,
				'countOutput' => null,
				'groupCount' => null,
				'preservekeys' => null,
				'sortfield' => '',
				'sortorder' => '',
				'limit' => null 
		);
		$options = zbx_array_merge ( $defOptions, $options );
		
		// permission check
		if (USER_TYPE_SUPER_ADMIN == $userType) {
		} elseif (is_null ( $options ['editable'] ) && self::$userData ['type'] == USER_TYPE_ZABBIX_ADMIN) {
		} elseif (! is_null ( $options ['editable'] ) || self::$userData ['type'] != USER_TYPE_SUPER_ADMIN) {
			return array ();
		}
		
		// valuemapids
		if (! is_null ( $options ['valuemapids'] )) {
			zbx_value2array ( $options ['valuemapids'] );
			$sqlParts ['where'] [] = dbConditionInt ( 'vm.valuemapid', $options ['valuemapids'] );
		}
		
		// with mappings
		if (!is_null($options['with_mappings'])) {
			$sqlParts ['select'] ['mappingid'] = 'm.mappingid';
			$sqlParts ['select'] ['value'] = 'm.value';
			$sqlParts ['select'] ['newvalue'] = 'm.newvalue';
			$sqlParts ['from'] ['mappings'] = 'mappings m';
			$sqlParts ['where'] ['mvm'] = 'm.valuemapid=vm.valuemapid';
		}
		
		// filter
		if (is_array ( $options ['filter'] )) {
			$this->dbFilter ( 'valuemaps vm', $options, $sqlParts );
			
			if ($this->dbFilter('mappings m', $options, $sqlParts)) {
				$sqlParts['from']['mappings'] = 'mappings m';
				$sqlParts['where']['mvm'] = 'm.valuemapid=vm.valuemapid';
			}
		}
		
		// search
		if (is_array ( $options ['search'] )) {
			zbx_db_search ( 'valuemaps vm', $options, $sqlParts );
		}
		
		// limit
		if (zbx_ctype_digit ( $options ['limit'] ) && $options ['limit']) {
			$sqlParts ['limit'] = $options ['limit'];
		}
		
		$sqlParts = $this->applyQueryOutputOptions ( $this->tableName (), $this->tableAlias (), $options, $sqlParts );
		$sqlParts = $this->applyQuerySortOptions ( $this->tableName (), $this->tableAlias (), $options, $sqlParts );
		$res = DBselect ( $this->createSelectQueryFromParts ( $sqlParts ), $sqlParts ['limit'] );
		while ( $valuemapping = DBfetch ( $res ) ) {
			if (! is_null ( $options ['countOutput'] )) {
				if (! is_null ( $options ['groupCount'] )) {
					$result [] = $valuemapping;
				} else {
					$result = $valuemapping ['rowscount'];
				}
			} else {
				if (! isset ( $result [$valuemapping ['valuemapid']] )) {
					$result [$valuemapping ['valuemapid']] = array ();
					$result [$valuemapping ['valuemapid']] ["valuemapid"] = $valuemapping ['valuemapid'];
					if (isset ( $valuemapping ['name'] )) {
						$result [$valuemapping ['valuemapid']] ["name"] = $valuemapping ['name'];
					}
				}
				
				if (isset ( $valuemapping ['mappingid'] )) {
					if (! isset ( $result [$valuemapping ['valuemapid']] ['mappings'] )) {
						$result [$valuemapping ['valuemapid']] ['mappings'] = array ();
					}
					
					$pos = count ( $result [$valuemapping ['valuemapid']] ['mappings'] );
					$result [$valuemapping ['valuemapid']] ['mappings'] [$pos] ['mappingid'] = $valuemapping ['mappingid'];
					$result [$valuemapping ['valuemapid']] ['mappings'] [$pos] ['value'] = $valuemapping ['value'];
					$result [$valuemapping ['valuemapid']] ['mappings'] [$pos] ['newvalue'] = $valuemapping ['newvalue'];
				}
			}
		}
		
		if (! is_null ( $options ['countOutput'] )) {
			return $result;
		}
		
		// removing keys (hash -> array)
		if (is_null ( $options ['preservekeys'] )) {
			$result = zbx_cleanHashes ( $result );
		}
		
		return $result;
	}

	/**
	 * Add Value Mapping
	 *
	 * @param array $valuemappings
	 * @param string $valuemappings['name']
	 * @param string $valuemappings['mappings']
	 * @param string $valuemappings['mappings'] [0] ['value']
	 * @param string $valuemappings['mappings'] [0] ['newvalue']
	 *                                         .
	 * @param string $valuemappings['mappings'] [x] ['value']
	 * @param string $valuemappings['mappings'] [x] ['newvalue']
	 * @return array|boolean
	 */
	public function create($valuemappings) {
		if (USER_TYPE_SUPER_ADMIN != self::$userData ['type']) {
			self::exception ( ZBX_API_ERROR_PERMISSIONS, _ ( 'Only Super Admins can create Value Mapping.' ) );
		}
		
		$valuemappings = zbx_toArray ( $valuemappings );
		
		foreach ( $valuemappings as $valuemapping ) {
			$valuemappingDbFields = array (
					'name' => null,
					'mappings' => null 
			);
			if (! check_db_fields ( $valuemappingDbFields, $valuemapping )) {
				self::exception ( ZBX_API_ERROR_PARAMETERS, _ ( 'Wrong fields for Value Mapping.' ) );
			}
			
			$valuemappingExist = $this->get ( array (
					'filter' => array (
							'name' => $valuemapping ['name'] 
					),
					'output' => API_OUTPUT_EXTEND 
			) );
			if (! empty ( $valuemappingExist )) {
				self::exception ( ZBX_API_ERROR_PARAMETERS, _s ( 'Value Mapping "%s" already exists.', $valuemappingExist [0] ['name'] ) );
			}
		}
		$valuemappingids = DB::insert ( 'valuemaps', $valuemappings );
		
		foreach ( $valuemappings as $pos => $valuemapping ) {
			if (isset ( $valuemappingids [$pos] )) {
				foreach ( $valuemapping ['mappings'] as $value ) {
					$value ['valuemapid'] = $valuemappingids [$pos];
					$this->addMapping ( $value );
				}
			} else {
				self::exception ( ZBX_API_ERROR_PARAMETERS, _s ( 'Id Not found "%s"', $pos . " : " . print_r ( $valuemappingids, true ) ) );
			}
		}
		
		return array (
				'valuemapids' => $valuemappingids 
		);
	}

	/**
	 * Update Value Mapping
	 *
	 * @param array $valuemappings
	 * @param string $valuemappings['valuemapid']
	 * @param string $valuemappings['name']
	 * @param string $valuemappings['mappings']
	 * @param string $valuemappings['mappings'] [0] ['type'] = add
	 * @param string $valuemappings['mappings'] [0] ['value']
	 * @param string $valuemappings['mappings'] [0] ['newvalue']
	 *                                         .
	 * @param string $valuemappings['mappings'] [x] ['type'] = remove
	 * @param string $valuemappings['mappings'] [x] ['mappingid']
	 * @return array
	 */
	public function update($valuemappings) {
		if (USER_TYPE_SUPER_ADMIN != self::$userData ['type']) {
			self::exception ( ZBX_API_ERROR_PERMISSIONS, _ ( 'Only Super Admins can edit value mapping.' ) );
		}
		
		$valuemappings = zbx_toArray ( $valuemappings );
		
		$update = array ();
		foreach ( $valuemappings as $valuemapping ) {
			$valuemappingDbFields = array (
					'valuemapid' => null,
					'name' => null,
					'mappings' => null 
			);
			if (! check_db_fields ( $valuemappingDbFields, $valuemapping )) {
				self::exception ( ZBX_API_ERROR_PARAMETERS, _ ( 'Wrong fields for Value Mapping.' ) );
			}
			unset ( $valuemapping ['mappings'] );
			
			$valuemappingid = $valuemapping ['valuemapid'];
			unset ( $valuemapping ['valuemapid'] );
			
			if (! empty ( $valuemapping )) {
				$update [] = array (
						'values' => $valuemapping,
						'where' => array (
								'valuemapid' => $valuemappingid 
						) 
				);
				DB::update ( 'valuemaps', $update );
			}
		}
		
		$valuemappingids = zbx_objectValues ( $valuemappings, 'valuemapid' );
		
		//Manage mappings
		foreach ( $valuemappings as $valuemapping ) {
			$valuemappingid = $valuemapping ['valuemapid'];
			foreach ( $valuemapping ['mappings'] as $ListValues ) {
				if (! isset ( $ListValues ['type'] )) {
					self::exception ( ZBX_API_ERROR_PARAMETERS, _s ( 'Mappings type add/remove is mandatory.', $valuemapping ['name'] ) );
				}
				$type = $ListValues ['type'];
				unset ( $ListValues ['type'] );
				switch ($type) {
					case 'add' :
						$ListValues ['valuemapid'] = $valuemappingid;
						$this->addMapping ( $ListValues );
						break;
					case 'remove' :
						$this->removeMapping ( $ListValues );
						break;
					default :
						self::exception ( ZBX_API_ERROR_PARAMETERS, _s ( 'Mappings type "%s" unknown.', $ListValues ['type'] ) );
				}
			}
		}
		
		return array (
				'valuemapids' => $valuemappingids 
		);
	}

	/**
	 * Delete Value Mapping.
	 *
	 * @param array $valuemappingids
	 *
	 * @return boolean
	 */
	public function delete($valuemappingids) {
		if (self::$userData ['type'] != USER_TYPE_SUPER_ADMIN) {
			self::exception ( ZBX_API_ERROR_PERMISSIONS, _ ( 'Only Super Admins can delete Value Mapping.' ) );
		}
		
		$valuemappingids = zbx_toArray ( $valuemappingids );

		DB::delete ( 'valuemaps', array (
				'valuemapid' => $valuemappingids 
		) );
		
		return array (
				'valuemapids' => $valuemappingids 
		);
	}

	/**
	 * Add one mapping
	 * @param array $value
	 * @param string $value ['value']
	 * @param string $value ['newvalue']
	 * @param string $value ['valuemapid']
	 */
	protected function addMapping($value) {
		$mappingsDbFields = array (
				'value' => null,
				'newvalue' => null,
				'valuemapid' => null 
		);
		if (! check_db_fields ( $mappingsDbFields, $value )) {
			self::exception ( ZBX_API_ERROR_PARAMETERS, _ ( 'Wrong fields for add Mappings.' ) );
		}
		
		DB::insert ( 'mappings', array (
				$value 
		) );
	}

	/**
	 * remove one mapping
	 * @param array $value
	 * @param string $value ['mappingid']
	 */
	protected function removeMapping($value) {
		$mappingsDbFields = array (
				'mappingid' => null 
		);
		if (! check_db_fields ( $mappingsDbFields, $value )) {
			self::exception ( ZBX_API_ERROR_PARAMETERS, _ ( 'Wrong fields for remove Mappings.' ) );
		}
		
		DB::delete ( 'mappings', array (
				'mappingid' => $value ['mappingid'] 
		) );
	}
}
