diff --git a/include/defines.inc.php b/include/defines.inc.php
index 3fb5b25..917787f 100644
--- a/include/defines.inc.php
+++ b/include/defines.inc.php
@@ -408,6 +408,9 @@ define('TRIGGER_VALUE_UNKNOWN', 2); // only in "events" table
 define('TRIGGER_VALUE_FLAG_NORMAL',		0);
 define('TRIGGER_VALUE_FLAG_UNKNOWN',	1);
 
+define('TRIGGER_FLAGS_PLAIN',	0);
+define('TRIGGER_FLAGS_DISCOVERED', 4);
+
 define('TRIGGER_VALUE_CHANGED_NO',	0);
 define('TRIGGER_VALUE_CHANGED_YES', 1);
 
@@ -458,6 +461,11 @@ define('ACTION_DEFAULT_MSG_DISCOVERY', "Discovery rule: {DISCOVERY.RULE.NAME}\n\
 		"Device service uptime: {DISCOVERY.SERVICE.UPTIME}"
 );
 
+define('SUCCEED',      1);
+define('FAIL',         0);
+define('MEDIA_STATUS_ACTIVE',         0);
+define('MEDIA_STATUS_DISABLED',         1);
+
 define('ACTION_STATUS_ENABLED',		0);
 define('ACTION_STATUS_DISABLED',	1);
 
@@ -479,6 +487,14 @@ define('ACTION_EVAL_TYPE_OR',		2);
 define('OPERATION_OBJECT_USER',		0);
 define('OPERATION_OBJECT_GROUP',	1);
 
+define('ESCALATION_STATUS_ACTIVE',	0);
+define('ESCALATION_STATUS_RECOVERY',	1);
+define('ESCALATION_STATUS_SLEEP',	2);
+define('ESCALATION_STATUS_COMPLETED',	3);
+//TODO: Relevant?
+define('ESCALATION_STATUS_SUPERSEDED_ACTIVE',	4);
+define('ESCALATION_STATUS_SUPERSEDED_RECOVERY',	5);
+
 define('LOGFILE_SEVERITY_NOT_CLASSIFIED',	0);
 define('LOGFILE_SEVERITY_INFORMATION',		1);
 define('LOGFILE_SEVERITY_WARNING',			2);
diff --git a/include/menu.inc.php b/include/menu.inc.php
index 6e27065..aae38fb 100644
--- a/include/menu.inc.php
+++ b/include/menu.inc.php
@@ -174,6 +174,7 @@ $ZBX_MENU = array(
 					'tr_logform.php',
 					'tr_testexpr.php',
 					'popup_trexpr.php',
+					'popup_action.php',
 					'host_discovery.php',
 					'disc_prototypes.php',
 					'trigger_prototypes.php'
diff --git a/include/views/configuration.triggers.list.php b/include/views/configuration.triggers.list.php
index 9ff3c07..f67fdb2 100644
--- a/include/views/configuration.triggers.list.php
+++ b/include/views/configuration.triggers.list.php
@@ -88,6 +88,7 @@ $link->setArgument('hostid', $this->data['hostid']);
 $link = $link->getUrl();
 
 $triggersTable = new CTableInfo(_('No triggers defined.'));
+//TODO: Hier Kopf ausgrauen?
 $triggersTable->setHeader(array(
 	new CCheckBox('all_triggers', null, "checkAll('".$triggersForm->getName()."', 'all_triggers', 'g_triggerid');"),
 	make_sorting_header(_('Severity'), 'priority', $link),
@@ -95,7 +96,8 @@ $triggersTable->setHeader(array(
 	make_sorting_header(_('Name'), 'description', $link),
 	_('Expression'),
 	make_sorting_header(_('Status'), 'status', $link),
-	empty($this->data['parent_discoveryid']) ? _('Error') : null
+	empty($this->data['parent_discoveryid']) ? _('Error') : null,
+	empty($this->data['action_test']) ? _('Action?') : null
 ));
 foreach ($this->data['triggers'] as $tnum => $trigger) {
 	$triggerid = $trigger['triggerid'];
@@ -192,6 +194,25 @@ foreach ($this->data['triggers'] as $tnum => $trigger) {
 		$status = new CLink(_('Enabled'), $status_link, 'enabled');
 	}
 
+        # TODO: Don't show for templates
+	//if ($user['type'] == USER_TYPE_SUPER_ADMIN) {
+	//	$actionsim_link = new CSpan(_('Actions?'), 'unknown');
+	//}
+	//else {
+	//	$actionsim_link = empty($this->data['action_test']) ? _('Action?') : null;
+	//}
+	//if ($user['type'] == USER_TYPE_SUPER_ADMIN) {
+                if ($trigger['status'] == TRIGGER_STATUS_ENABLED) {
+                        $action_test = new CButton('actions', _('Actions?'), 'return PopUp("popup_action.php?dstfrm=action&triggerid='.$triggerid.'", 700, 500);', 'link_menu');
+                }
+                # Trigger disabled or on a template
+                elseif ($trigger['status'] == TRIGGER_STATUS_DISABLED)  {
+                        $action_test = null;
+                }
+	//}
+
+
+
 	$hosts = null;
 	if (empty($this->data['hostid'])) {
 		foreach ($trigger['hosts'] as $hostid => $host) {
@@ -215,7 +236,8 @@ foreach ($this->data['triggers'] as $tnum => $trigger) {
 		$description,
 		$expressionColumn,
 		$status,
-		$error
+		$error,
+		$action_test
 	));
 	$triggers[$tnum] = $trigger;
 }
diff --git a/popup_action.php b/popup_action.php
new file mode 100644
index 0000000..6741e7a
--- /dev/null
+++ b/popup_action.php
@@ -0,0 +1,1188 @@
+<?php
+/*
+** 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.
+**/
+
+//TODO: Collapsing in action debugging table doesn't work
+//TODO: Get calendar working
+//TODO: Use time from form
+//TODO: You can't uncheck the maintenace button anymore
+//TODO: Use real maintenances, based on trigger hosts
+//TODO: Hide from non-super-admins
+//TODO: Separate presentation into a view file
+//TODO: Revise function names
+
+require_once dirname(__FILE__).'/include/actions.inc.php';
+require_once dirname(__FILE__).'/include/config.inc.php';
+require_once dirname(__FILE__).'/include/items.inc.php';
+require_once dirname(__FILE__).'/include/triggers.inc.php';
+require_once dirname(__FILE__).'/include/forms.inc.php';
+require_once dirname(__FILE__).'/include/perm.inc.php';
+require_once dirname(__FILE__).'/include/js.inc.php';
+
+$page['title'] = _('Action simulator');
+$page['file'] = 'popup_action.php';
+$page['scripts'] = array('class.calendar.js');
+
+
+define('ZBX_PAGE_NO_MENU', 1);
+
+require_once dirname(__FILE__).'/include/page_header.php';
+
+//TODO: Rather via menu.inc.php
+//As an example: Columns in search results are just greyed out for unpriviledged users
+if ($USER_DETAILS['type'] != USER_TYPE_SUPER_ADMIN) {
+	access_deny();
+}
+
+//		VAR			TYPE	OPTIONAL FLAGS	VALIDATION	EXCEPTION
+$fields = array(
+	'dstfrm'=>		array(T_ZBX_STR, O_MAND,P_SYS,	NOT_EMPTY,		NULL),
+	'triggerid'=>   array(T_ZBX_INT, O_MAND,P_SYS,	NOT_EMPTY,		NULL),
+	'maint'=>	    array(T_ZBX_INT, O_OPT,	P_SYS,	IN('0,1'),	NULL),
+	'close'=>		array(T_ZBX_INT, O_OPT,	NULL,	IN('1'),	NULL),
+	'open'=>		array(T_ZBX_INT, O_OPT,	NULL,	IN('1'),	NULL),
+
+/* other */
+	'form'=>		array(T_ZBX_STR, O_OPT, P_SYS,	NULL,	NULL),
+);
+
+check_fields($fields);
+
+
+if (!isset($_REQUEST['maint'])) {
+	$_REQUEST['maint'] = 0;
+}
+
+if(isset($_REQUEST['open'])){
+	$showAll = 1;
+}
+else{
+	$hideAll = 1;
+}
+
+if(isset($showAll)){
+	$url = '?close=1'.
+		url_param('groupid').
+		url_param('hostid').
+		url_param('select');
+	$link = new CLink(new CImg('images/general/minus.png'),$url);
+}
+else{
+	$url = '?open=1'.
+		url_param('groupid').
+		url_param('hostid').
+		url_param('select');
+	$link = new CLink(new CImg('images/general/plus.png'),$url);
+}
+
+
+$triggerid = get_request('triggerid');
+$period = get_request('period', ZBX_DEFAULT_INTERVAL);
+
+$debug = array();
+$debug_messaging = array();
+
+/////////////////////////////////////
+
+function action_evaltype2str($evaltype) {
+    $str_type[ACTION_EVAL_TYPE_AND_OR] = _('AND/OR');
+    $str_type[ACTION_EVAL_TYPE_AND] = _('AND');
+    $str_type[ACTION_EVAL_TYPE_OR] = _('OR');
+
+    if (isset($str_type[$evaltype])) {
+        return $str_type[$evaltype];
+    }    
+
+    return _('Unknown');
+}
+
+
+// Map script id to script name
+function get_global_script_name($scriptid) {
+	$script = API::Script()->get(array(
+            'scriptids' => array($scriptid),
+            'output' => API_OUTPUT_EXTEND,
+            'preservekeys' => '1'
+        ));
+
+    if ($script) {
+        $script = reset($script);
+        return $script['name'];
+    }
+
+    return _('Unknown');
+}
+
+
+// Map numerical script type to textual script type
+function operation_scripttype2str($scripttype) {
+    $str_type[ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT] = _('Custom script');
+    $str_type[ZBX_SCRIPT_TYPE_IPMI] = _('IPMI');
+    $str_type[ZBX_SCRIPT_TYPE_SSH] = _('SSH');
+    $str_type[ZBX_SCRIPT_TYPE_TELNET] = _('Telnet');
+    $str_type[ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT] = _('Global script');
+
+    if (isset($str_type[$scripttype])) {
+        return $str_type[$scripttype];
+    }    
+
+    return _('Unknown');
+}
+        
+    //Possible reasons for operations to fail
+    //System -- per user
+    //Host -- per trigger
+    //Severity -- per trigger
+    //Time -- per trigger time and media settings
+    //Media not defined
+    //Medium inactive
+
+function process_actions($data) {
+    //TODO: Only works properly for Super Admins, because there are permission restrictions
+	//TODO: DBstart_escalation and DBstop_escalation
+	//r_eventid is filled with eventid, when escalation is stopped. It's an insert statement though!
+	$actions = API::Action()->get(array(
+            'selectConditions' => API_OUTPUT_EXTEND,
+            'selectOperations' => API_OUTPUT_EXTEND,
+            'output' => API_OUTPUT_EXTEND,
+	        'filter' => array('status' => '0', 'eventsource' => '0'),
+	));
+
+    $valid_actions = array();
+    foreach ($actions as $action) {
+		$escalation[] = array();
+		$actionid = $action['actionid'];
+		$hosts = reset($data);
+
+        if (check_action_conditions($action, $data) == SUCCEED) {
+            $valid_actions[] = $action;
+            
+	//		//TODO: Woher escalationid und wozu? Eventid gibt es keine
+	//		$valid_actions[] = array('actionid' => $actionid,
+	//			'triggerid' => $triggerid,
+	//			'status' => ESCALATION_STATUS_ACTIVE
+	//		);
+	//	}
+	//	//TODO: Hä?
+	//	else {
+	//		//Hier wäre dann die r_eventid sofern ich die brauch.
+	//		$valid_actions[] = array('actionid' => $actionid,
+	//			'triggerid' => $triggerid,
+	//			'status' => ESCALATION_STATUS_ACTIVE
+	//		);
+            
+        }
+    }
+
+    $notifications = execute_operations($data['hosts'][0]['hostid'], $data['priority'], $valid_actions);
+    $commands = execute_commands($valid_actions);
+    
+    return array('notifications' => $notifications, 'commands' => $commands);
+}
+
+
+// Check conditions of all active actions for a given trigger
+// Parameters:
+// action -- Array of all active actions
+// data -- Trigger to check actions for
+function check_action_conditions($action, $data) {
+        
+    global $debug;
+
+    $exit = 0;
+    $old_type = -1;
+    $cond = -1;
+    $ret = SUCCEED;
+    $conditiontypes = array();
+    
+    //Sort by conditiontype within the action, otherwise evaluation can fail
+    foreach ($action['conditions'] as $condition) {
+        $conditiontypes[] = $condition['conditiontype'];
+    }
+
+    array_multisort($conditiontypes, SORT_ASC, $action['conditions']);
+
+    $actionid = $action['actionid'];
+    $debug[$actionid] = array('name' => $action['name'], 'evaltype' => $action['evaltype']);
+
+    foreach ($action['conditions'] as $condition) {
+        $conditionid = $condition['conditionid'];
+        if ($exit == 0) {
+            switch ($action['evaltype']) {
+                case ACTION_EVAL_TYPE_AND_OR:
+                    // OR part of conditions
+                    if ($old_type == $condition['conditiontype']) {
+                        if (check_trigger_condition($condition, $data) == SUCCEED) {
+                            $ret = SUCCEED;
+                        }
+                    }
+                    // AND part of conditions
+                    else {
+                        // Break if PREVIOUS AND condition is FALSE
+                        if ($ret == FAIL) {
+                            $exit = 1;
+                        }
+                        //HIER könnte das Problem liegen
+                        elseif (check_trigger_condition($condition, $data) == FAIL) {
+                            $ret = FAIL;
+                        }
+                    }
+
+                    $old_type = $condition['conditiontype'];
+
+                    break;
+                
+                case ACTION_EVAL_TYPE_AND:
+                    $cond = check_trigger_condition($condition, $data);
+                    // break if any AND condition is FALSE
+                    if ($cond == FAIL) {
+                        $ret = FAIL;
+                        $exit = 1;
+                    }
+                    else {
+                        $ret = SUCCEED;
+                    }
+                    
+                    break;
+
+                case ACTION_EVAL_TYPE_OR:
+                    $cond = check_trigger_condition($condition, $data);
+                    // break if any OR condition is TRUE
+                    if ($cond == SUCCEED) {
+                        $ret = SUCCEED;
+                        $exit = 1;
+                    }
+                    else {
+                        $ret = FAIL;
+                    }
+                    
+                    break;
+            }
+        }
+        elseif ($exit == 1) {
+            break;
+        }
+    }
+    return $ret;
+}
+
+
+//Check one trigger condition for a match
+//Parameters:
+//condition -- Action condition
+//data -- Trigger to match
+function check_trigger_condition($condition, $data){
+    
+    //DEBUG
+    global $debug;
+    $actionid = $condition['actionid'];
+    $conditionid = $condition['conditionid'];
+    $debug[$actionid]['conditions'][$conditionid]['conditiontype'] = $condition['conditiontype'];
+    $debug[$actionid]['conditions'][$conditionid]['operator'] = $condition['operator'];
+    $debug[$actionid]['conditions'][$conditionid]['conditionvalue'] = $condition['value'];
+    
+    $ret = FAIL;
+
+    if ($condition['conditiontype'] == CONDITION_TYPE_HOST_GROUP) {
+
+        $condition_matches = API::Trigger()->get(array(
+                'groupids' => array($condition['value']),
+                'triggerids' => array($data['triggerid'])
+        ));
+
+        $hostgroups = API::HostGroup()->get(array(
+            'triggerids' => array($data['triggerid'])
+        ));
+        $hostgroupslist = array();
+        foreach ($hostgroups as $hostgroup) {
+            $hostgrouplist[] = $hostgroup['groupid'];
+        }
+
+        $debug[$actionid]['conditions'][$conditionid]['actualvalue'] = $hostgrouplist;
+
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_EQUAL:
+                if ($condition_matches) {
+                    $ret = SUCCEED;
+                }
+                break;
+            case CONDITION_OPERATOR_NOT_EQUAL:
+                if (!$condition_matches) {
+                    $ret = SUCCEED;
+                }
+                break;
+        }
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_HOST_TEMPLATE) {
+        switch ($condition['operator']) {
+        case CONDITION_OPERATOR_EQUAL:
+            case CONDITION_OPERATOR_NOT_EQUAL:
+                $triggerid = $data['triggerid'];
+
+                # Use parent trigger ID for generated triggers
+                if ($data['flags'] == TRIGGER_FLAGS_DISCOVERED) {
+                    $sql = 'SELECT parent_triggerid'.
+                        ' FROM trigger_discovery'.
+                        ' WHERE triggerid='.$triggerid;
+                    $triggerid = DBfetch(DBselect($sql));
+                    $triggerid = reset($triggerid);
+                }
+
+                //Loop until you hit the base template
+                while ($ret != SUCCEED and $triggerid != 0){
+                    $condition_matches = API::Trigger()->get(array(
+                        'triggerids' => $triggerid,
+                        'selectHosts' => API_OUTPUT_EXTEND,
+                        'output' => API_OUTPUT_EXTEND,
+                    ));
+
+                    // trigger.get does not return trigger prototypes
+                    if (!$condition_matches) {
+                        $condition_matches = API::TriggerPrototype()->get(array(
+                            'triggerids' => $triggerid,
+                            'selectHosts' => API_OUTPUT_EXTEND,
+                            'output' => API_OUTPUT_EXTEND,
+                        ));
+                    }
+
+                    $condition_matches = reset($condition_matches);
+                    if ($condition_matches) {
+
+                        //TODO: Remove API calls above?
+                        $triggerid = $condition_matches['templateid'];
+                        $templateid = API::Template()->get(array(
+                            'triggerids' => $triggerid,
+                            'output' => API_OUTPUT_EXTEND,
+                        ));
+                        if ($templateid) {
+                            $templateid = reset($templateid);
+                            //TODO: Turn to host instead?
+                            $debug[$actionid]['conditions'][$conditionid]['actualvalue'][] = $templateid['hostid'];
+                        }
+
+                        if ($condition_matches['hosts'][0]['hostid'] == $condition['value']) {
+                            $ret = SUCCEED;
+                            break;
+                        }
+                    }
+                    else {
+                        $triggerid = 0;
+                    }
+                }
+                if ($condition['operator'] == CONDITION_OPERATOR_NOT_EQUAL) {
+                    $ret = ($ret == SUCCEED) ? FAIL : SUCCEED;
+                    break;
+                }
+        }
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_HOST) {
+
+        $debug[$actionid]['conditions'][$conditionid]['actualvalue'] = $data['hosts'][0]['hostid'];
+
+        if ($data['hosts'][0]['hostid'] == $condition['value']) {
+            $condition_matches = 1;
+        }
+        else {
+            $condition_matches = 0;
+        }
+
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_EQUAL:
+                if ($condition_matches == 1){
+                    $ret = SUCCEED;}
+                break;
+            case CONDITION_OPERATOR_NOT_EQUAL:
+                if ($condition_matches == 0){
+                    $ret = SUCCEED;}
+                break;
+        }
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_TRIGGER) {
+
+        $debug[$actionid]['conditions'][$conditionid]['actualvalue'] = $data['triggerid'];
+
+        if ($data['triggerid'] == $condition['value']) {
+            $condition_matches = 1;
+        }
+        else {
+            $condition_matches = 0;
+        }
+
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_EQUAL:
+                if ($condition_matches == 1)
+                    $ret = SUCCEED;
+                break;
+            case CONDITION_OPERATOR_NOT_EQUAL:
+                if ($condition_matches == 0)
+                    $ret = SUCCEED;
+                break;
+        }
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_TRIGGER_NAME) {
+
+        $debug[$actionid]['conditions'][$conditionid]['actualvalue'] = $data['description'];
+
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_LIKE:
+                if (strstr($data['description'], $condition['value'])) {
+                    $ret = SUCCEED;
+                }
+                break;
+            case CONDITION_OPERATOR_NOT_LIKE:
+                if (!strstr($data['description'], $condition['value'])) {
+                    $ret = SUCCEED;
+                }
+                break;
+        }
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_TRIGGER_SEVERITY) {
+
+        $debug[$actionid]['conditions'][$conditionid]['actualvalue'] = $data['priority'];
+
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_EQUAL:
+                if ($data['priority'] == $condition['value']) {
+                    $ret = SUCCEED;
+                }
+                break;
+            case CONDITION_OPERATOR_NOT_EQUAL:
+                if ($data['priority'] != $condition['value']) {
+                    $ret = SUCCEED;
+                }
+                break;
+            case CONDITION_OPERATOR_MORE_EQUAL:
+                if ($data['priority'] >= $condition['value']) {
+                    $ret = SUCCEED;
+                }
+                break;
+            case CONDITION_OPERATOR_LESS_EQUAL:
+                if ($data['priority'] <= $condition['value']) {
+                    $ret = SUCCEED;
+                }
+                break;
+        }
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_TRIGGER_VALUE) {
+
+        $debug[$actionid]['conditions'][$conditionid]['actualvalue'] = 'Don\'t care';
+
+        //TODO: Not implemented yet; should only be relevant for recovery messages
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_EQUAL:
+                break;
+        }
+        $ret = SUCCEED;
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_TIME_PERIOD) {
+        $time_periods = explode(';', $condition['value']);
+        //TODO: Korrigieren und Format
+        $debug[$actionid]['conditions'][$conditionid]['actualvalue'] = zbx_date2str(_('D, H:i'), time());
+        
+        //TODO: Später zbx_date2age
+
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_IN:
+                foreach ($time_periods as $time_period) {
+                    //TODO: Use time from form
+                    if (checkTimePeriod($time_period, time())) {
+                        $ret = SUCCEED;
+                        break;
+                    }
+                }
+                break;
+            case CONDITION_OPERATOR_NOT_IN:
+                foreach ($time_periods as $time_period) {
+                    if (checkTimePeriod($time_period, time())) {
+                        break;
+                    }
+                    $ret = SUCCEED;
+                }
+                break;
+        }
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_MAINTENANCE) {
+
+        //TODO: Integrate real maintenance periods
+        $debug[$actionid]['conditions'][$conditionid]['actualvalue'] = $_REQUEST['maint'];
+
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_IN:
+	            if ($_REQUEST['maint'] == HOST_MAINTENANCE_STATUS_ON) {
+                    $ret = SUCCEED;
+                }
+                break;
+            case CONDITION_OPERATOR_NOT_IN:
+	            if ($_REQUEST['maint'] == HOST_MAINTENANCE_STATUS_OFF) {
+                    $ret = SUCCEED;
+                }
+                break;
+        }
+    }
+    elseif ($condition['conditiontype'] == CONDITION_TYPE_APPLICATION) {
+        $items = array_map(function($item) {return $item['itemid'];}, $data['items']);
+        //No output customization possible
+        $applications = API::Application()->get(array(
+            'itemids' => $items,
+	    'output' => API_OUTPUT_EXTEND
+            ));
+
+        
+        if ($applications) {
+            foreach ($applications as $app) {
+                $debug[$actionid]['conditions'][$conditionid]['actualvalue'][] = $app['name'];
+            }
+        }
+        else {
+            // Item has no application defined
+            $debug[$actionid]['conditions'][$conditionid]['actualvalue'][] = '';
+        }
+
+        switch ($condition['operator']) {
+            case CONDITION_OPERATOR_EQUAL:
+                foreach ($applications as $app) {
+                   if (strcmp($app['name'], $condition['value']) == 0){
+                       $ret = SUCCEED;
+                       break;
+                   }
+                }
+                break;
+            case CONDITION_OPERATOR_LIKE:
+                //Das scheint leer zu sein.
+                foreach ($applications as $app) {
+                   if (strstr($app['name'], $condition['value'])){
+                       $ret = SUCCEED;
+                       break;
+                   }
+                }
+                break;
+            case CONDITION_OPERATOR_NOT_LIKE:
+                $ret = SUCCEED;
+                foreach ($applications as $app) {
+                   if (strstr($app['name'], $condition['value'])){
+                       $ret = FAIL;
+                       break;
+                   }
+                }
+                break;
+        }
+    }
+
+    $debug[$actionid]['conditions'][$conditionid]['status'] = $ret;
+
+    return $ret;
+}
+
+
+// Make sure host is readable to the specified user
+//
+// Parameters:
+// userid -- userid of the user in question
+// hostid -- hostid for the host in question
+//
+// Return values:
+// SUCCEED -- User has read access to the host
+// FAIL -- User has no read access to the host
+function get_host_permissions($userid, $hostid) {
+
+    // Is this nessary?
+    $user = API::User()->get(array(
+        'userids' => $userid,
+        'output' => API_OUTPUT_EXTEND
+    ));
+    $user = reset($user);
+
+    if ($user['type'] == USER_TYPE_SUPER_ADMIN) {
+        $ret = SUCCEED;
+        return $ret;
+    }
+
+    $sql = 'SELECT MIN(r.permission)'.
+           ' FROM rights r, hosts_groups hg, users_groups ug'.
+           ' WHERE r.groupid=ug.usrgrpid'.
+            ' AND r.id=hg.groupid'.
+            ' AND hg.hostid='.$hostid.
+            ' AND ug.userid='.$userid;
+    $permission = DBfetch(DBselect($sql));
+    //TODO: Gertjan: It seems like the result of this query can be invalid, but I wonder why. Possibly a result of just being a Zabbix Admin user type?
+    if ($permission AND $permission['min'] > PERM_DENY) {
+        $ret = SUCCEED;
+    }
+    else {
+        $ret = FAIL;
+    }
+
+    return $ret;
+}
+
+//Processes remote commands for all given actions
+function execute_commands($valid_actions) {
+    $results = array();
+    foreach ($valid_actions as $valid_action) {
+        foreach ($valid_action['operations'] as $operation) {
+            if ($operation['operationtype'] == OPERATION_TYPE_COMMAND) {
+                $opcommand = $operation['opcommand'];
+                $script = '';
+
+                switch ($opcommand['type']) {
+                case ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT:
+                    if ($opcommand['execute_on'] == ZBX_SCRIPT_EXECUTE_ON_AGENT) {
+                        $script .= 'Execute on Agent:'.SPACE;
+                    }
+                    else if ($opcommand['execute_on'] == ZBX_SCRIPT_EXECUTE_ON_SERVER) {
+                        $script .= 'Execute on Server:'.SPACE;
+                    }
+                    break;
+                case ZBX_SCRIPT_TYPE_SSH:
+                    //Better show no details
+                    case ZBX_SCRIPT_TYPE_TELNET:
+                        //Better show no details
+                        break;
+                    case ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT:
+                        $script .= get_global_script_name($opcommand['scriptid']);
+                }
+
+                if ($opcommand['type'] != ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT) {
+                    //TODO: Macros, if necessary
+                    $script .= $opcommand['command'];
+                }
+
+                $results[] = array(
+                    'opdesc' => get_operation_desc(SHORT_DESCRIPTION, $operation),
+                    'action_name' => $valid_action['name'],
+                    'type' => $opcommand['type'],
+                    'command' => $script,
+                    'esc_step_from' => $operation['esc_step_from'],
+                    'esc_step_to' => $operation['esc_step_to']
+                );
+            }
+        }
+    }
+    return $results;
+}
+
+//Check user's system and host permissions
+//
+//Returns a list of resulting notifications so far
+function add_user_msg($hostid, $earlier_results) {
+
+    global $debug_messaging;
+
+    $preliminary_results = array();
+
+    //User is enabled and allowed to receive notification for this host
+    foreach ($earlier_results as $earlier_result) {
+        $userid = $earlier_result['userid'];
+
+        if (!check_perm2system($userid)) {
+            //Debug
+            $debug_message = $earlier_result;
+            $debug_message['error'] = 'User is not allowed to access Zabbix';
+            $debug_messaging[] = $debug_message;
+            continue;
+        }
+        
+        if (get_host_permissions($userid, $hostid) == SUCCEED) {
+            $preliminary_results[] = $earlier_result;
+        }
+        else {
+            $debug_message = $earlier_result;
+            $debug_message['error'] = 'Host permissions';
+            $debug_message['mediatypeid'] = '';
+            $debug_message['sendto'] = '';
+            $debug_messaging[] = $debug_message;
+        }
+    }
+    return $preliminary_results;
+}
+
+
+//Resolve user groups in operations and create preliminary results
+function add_object_msg($hostid, $priority, $action_name, $operation) {
+
+    //TODO: Should rather be "resultS"
+    $preliminary_result = array();
+    $mediatypeid = $operation['opmessage']['mediatypeid'];
+
+    //Operations on per user-group basis
+    if ($operation['opmessage_grp']) {
+        $usergroups = array_map(function($item) {return $item['usrgrpid'];}, $operation['opmessage_grp']);
+
+        //Multiple user groups can be specified per operation
+        //TODO: Merge branches
+        foreach ($usergroups as $usergroup) {
+            $users = API::UserGroup()->get(array(
+                'usrgrpids' => $usergroup,
+                'selectUsers' => API_OUTPUT_EXTEND
+            ));
+            $users = reset($users);
+            foreach ($users['users'] as $user) {
+                $preliminary_result[] = array(
+                    'actionid' => $operation['actionid'],
+                    'action_name' => $action_name,
+                    'alias' => $user['alias'],
+                    'userid' => $user['userid'],
+                    'opdesc' => get_operation_desc(SHORT_DESCRIPTION, $operation),
+                    'esc_period' => $operation['esc_period'],
+                    'esc_step_from' => $operation['esc_step_from'],
+                    'esc_step_to' => $operation['esc_step_to'],
+                    'mediatypeid' => $mediatypeid
+                );
+            }
+        }
+    }
+
+    //Operations on per user basis
+    if ($operation['opmessage_usr']) {
+        $users = array_map(function($item) {return $item['userid'];}, $operation['opmessage_usr']);
+
+        //Multiple users can be specified per operation
+        foreach ($users as $user) {
+            $users = API::User()->get(array(
+                'userids' => $user,
+                'output' => API_OUTPUT_EXTEND
+            ));
+
+            foreach ($users as $user) {
+                $preliminary_result[] = array(
+                    'actionid' => $operation['actionid'],
+                    'action_name' => $action_name,
+                    'alias' => $user['alias'],
+                    'userid' => $user['userid'],
+                    'opdesc' => get_operation_desc(SHORT_DESCRIPTION, $operation),
+                    'esc_period' => $operation['esc_period'],
+                    'esc_step_from' => $operation['esc_step_from'],
+                    'esc_step_to' => $operation['esc_step_to'],
+                    'mediatypeid' => $mediatypeid
+                );
+            }
+        }
+    }
+    $notifications = add_user_msg($hostid, $preliminary_result);
+    //TODO: Check for empty arrays
+    return $notifications;
+}
+
+
+// Resolves effective media types for users and user groups,
+// if no specific media type was specified
+// Parameters:
+// priority -- Severity number code of trigger
+function add_message_alert($priority, $preliminary_results) {
+
+    //DEBUG
+    global $debug_messaging;
+
+    $results = array();
+
+	//All defined media types
+    $mediatypes = API::Mediatype()->get(array(
+        'output' => API_OUTPUT_EXTEND,
+        'preservekeys' => '1'
+    ));
+
+    foreach ($preliminary_results as $preliminary_result) {
+        if ($preliminary_result['mediatypeid'] == 0) {
+            //No specific media type given
+            //This API call ignores system-wide settings for media types
+            $usermedias = API::UserMedia()->get(array(
+                'userids' => $preliminary_result['userid'],
+                'output' => API_OUTPUT_EXTEND
+            ));
+        }
+        else {
+            //Specific media type given
+            $usermedias = API::UserMedia()->get(array(
+                'userids' => $preliminary_result['userid'],
+                'mediatypeids' => $preliminary_result['mediatypeid'],
+                'output' => API_OUTPUT_EXTEND
+            ));
+        }
+
+        if ($usermedias) {
+			//Compare severity and activity setting for each active user media intended for notification
+            foreach ($usermedias as $usermedia) {
+                //TODO: Seems like this can still be empty on occasions, see different_machine,
+                //Two-items trigger, different machines OR; Admin SMS -- Lost context of this comment!
+
+                $sendto = $usermedia['sendto'];
+				$mediatype = $mediatypes[$usermedia['mediatypeid']]['description'];
+
+				if ($mediatypes[$usermedia['mediatypeid']]['status'] == MEDIA_TYPE_STATUS_DISABLED) {
+					//Debug
+					$debug_message = $preliminary_result;
+					$debug_message['error'] = 'Media type disabled system-wide';
+					$debug_message['mediatypeid'] = $mediatype;
+					$debug_message['sendto'] = $sendto;
+					$debug_messaging[] = $debug_message;
+					continue;
+				}
+				
+				if ($usermedia['active'] == MEDIA_STATUS_DISABLED) {
+					//Debug
+					$debug_message = $preliminary_result;
+					$debug_message['error'] = 'Media type disabled for user';
+					$debug_message['mediatypeid'] = $mediatype;
+					$debug_message['sendto'] = $sendto;
+					$debug_messaging[] = $debug_message;
+                    continue;
+		}
+
+                if((1 << $priority & $usermedia['severity']) == 0) {
+                    //Check for matching severity settings
+
+                    //Debug
+                    $debug_message = $preliminary_result;
+                    $debug_message['error'] = 'Severity doesn\'t match media type settings';
+                    $debug_message['mediatypeid'] = $mediatype;
+                    $debug_message['sendto'] = $sendto;
+                    $debug_messaging[] = $debug_message;
+                    continue;
+                }
+
+                //TODO: Use time from form
+                $periods = explode(';', $usermedia['period']);
+                $period_match = false;
+                foreach ($periods as $period) {
+                    // One period must match to succeed
+                    if (CheckTimePeriod($period, time())) {
+                        $period_match = true;
+                        break;
+                    }
+                }
+
+                if (!$period_match) {
+                    //Debug
+                    $debug_message = $preliminary_result;
+                    $debug_message['error'] = 'Time doesn\'t match media type settings';
+                    $debug_message['mediatypeid'] = $mediatype;
+                    $debug_message['sendto'] = $sendto;
+                    $debug_messaging[] = $debug_message;
+                    continue;
+                }
+
+                $preliminary_result['mediatypeid'] = $mediatype;
+                $preliminary_result['sendto'] = $sendto;
+
+                $results[] = $preliminary_result;
+            }
+        }
+        else {
+            //Debug
+            $debug_message = $preliminary_result;
+            $debug_message['error'] = 'Media type not defined for user';
+
+            # All media types desired but none defined
+			if ($preliminary_result['mediatypeid'] == 0) {
+				$debug_message['mediatypeid'] = 'All';
+			}
+			else {
+				$debug_message['mediatypeid'] = $mediatypes[$preliminary_result['mediatypeid']]['description'];
+			}
+            $debug_message['sendto'] = '';
+            $debug_messaging[] = $debug_message;
+        }
+    }
+    return $results;
+}
+
+
+function execute_operations($hostid, $priority, $actions) {
+
+    $result = array();
+
+    foreach ($actions as $action) {
+        foreach ($action['operations'] as $operation) {
+            // Messaging
+            if ($operation['operationtype'] == OPERATION_TYPE_MESSAGE) {
+                $result = array_merge(add_object_msg($hostid, $priority, $action['name'], $operation), $result);
+            }
+        }
+    }
+    
+    $final = add_message_alert($priority, $result);
+    return $final;
+}
+
+//////////////////////
+
+$data = API::Trigger()->get(array(
+	'triggerids' => $triggerid,
+    'expandDescription' => '1',
+	'output' => API_OUTPUT_EXTEND,
+	'selectGroups' => API_OUTPUT_EXTEND,
+	'selectHosts' => API_OUTPUT_EXTEND,
+	'selectItems' => API_OUTPUT_REFER,
+	'selectFunctions' => API_OUTPUT_EXTEND,
+	'selectDependencies' => API_OUTPUT_EXTEND
+));
+$data = reset($data);
+
+$frmAction = new CFormTable(_('Action simulator'));
+$frmAction->setName('frmAction');
+$frmAction->addVar('dstfrm', $_REQUEST['dstfrm']);
+$frmAction->addVar('triggerid', $_REQUEST['triggerid']);
+
+$trigger = $data['description'];
+$description = array();
+
+// Taken from include/views/configuration.triggers.list.php
+$dependencies = $data['dependencies'];
+if (count($dependencies) > 0) {
+	foreach ($dependencies as $dep_trigger) {
+
+		$db_hosts = get_hosts_by_triggerid($dep_trigger['triggerid']);
+		while ($host = DBfetch($db_hosts)) {
+			$description[] = $host['name'];
+			$description[] = ', ';
+		}
+		array_pop($description);
+		$description[] = ' : ';
+		$description[] = $dep_trigger['description'];
+        $description[] = BR();
+	}
+}
+
+
+$results = process_actions($data);
+$notifications = $results['notifications'];
+$commands = $results['commands'];
+
+$trigger_table = new CTableInfo(_('No trigger -- something went wrong'));
+$notification_table = new CTableInfo(_('No notification'));
+$debug_messaging_table = new CTableInfo(_('No messaging considered'));
+$command_table = new CTableInfo(_('No remote commands'));
+$debug_table = new CTableInfo(_('No actions found'));
+
+$frmAction->addVar('trigger_at', date('YmdHi'));
+
+$calendarIcon = new CImg('images/general/bar/cal.gif', 'calendar', 16, 12, 'pointer'); 
+$calendarIcon->addAction('onclick', 'javascript: var pos = getPosition(this); pos.top += 10; pos.left += 16; CLNDR["trigger_at"].clndr.clndrshow(pos.top, pos.left); CLNDR["trigger_at"].clndr.clndrhide();');
+$triggerAtDay = new CNumericBox('trigger_at_day', date('d'), 2);
+$triggerAtDay->setAttribute('placeholder', _('dd'));
+$triggerAtMonth = new CNumericBox('trigger_at_month', date('m'), 2);
+$triggerAtMonth->setAttribute('placeholder', _('mm'));
+$triggerAtYear = new CNumericBox('trigger_at_year', date('Y'), 4);
+$triggerAtYear->setAttribute('placeholder', _('yyyy'));
+$triggerAtHour = new CNumericBox('trigger_at_hour', date('H'), 2);
+$triggerAtHour->setAttribute('placeholder', _('hh'));
+$triggerAtMinute = new CNumericBox('trigger_at_minute', date('i'), 2);
+
+$ackOption = new CCheckbox('maint', $_REQUEST['maint'], null, 1);
+$maintenanceFormList = new CFormList('maintenanceFormList');
+$triggerDateForm = array($triggerAtDay, '/', $triggerAtMonth, '/', $triggerAtYear, SPACE, $triggerAtHour, ':', $triggerAtMinute, $calendarIcon);
+$ackDateForm = array($triggerAtDay, '/', $triggerAtMonth, '/', $triggerAtYear, SPACE, $triggerAtHour, ':', $triggerAtMinute, $calendarIcon, SPACE, $ackOption, SPACE, _('NI Acknowledged?'));
+$resolvedDateForm = array($triggerAtDay, '/', $triggerAtMonth, '/', $triggerAtYear, SPACE, $triggerAtHour, ':', $triggerAtMinute, $calendarIcon);
+zbx_add_post_js('create_calendar(null, ["trigger_at_day", "trigger_at_month", "trigger_at_year", "trigger_at_hour", "trigger_at_minute"], "trigger_at", "trigger_at");');
+
+$trigger_table->addRow(array('Host', $data['hosts'][0]['host']));
+$trigger_table->addRow(array('Trigger', $trigger));
+$trigger_table->addRow(array('Severity', getSeverityCell($data['priority'])));
+//TODO: Phase out, replace with real periods
+$trigger_table->addRow(array(_('Maintenance'), new CCheckbox('maint', $_REQUEST['maint'], null, 1)));
+$trigger_table->addRow(array(_('NI Trigger time'), $triggerDateForm));
+//TODO: Checkbox for ack
+//TODO: Consider real maintenance periods
+$trigger_table->addRow(array(_('NI Acknodwledged at'), $ackDateForm));
+$trigger_table->addRow(array(_('NI Resolved at'), $resolvedDateForm));
+if ($description) {
+    $trigger_table->addRow(array(_('Depends on'), $description));
+}
+
+    //TODO: Formatter functions
+$notification_table->setHeader(array(
+	_('Escalation step'),
+    _('Time passed'),
+    _('Time'),
+	_('Action name'),
+	_('Escalation steps for op.'),
+	_('Operation'),
+	_('Media type'),
+	_('Alias'),
+	_('Send To'),
+));
+
+$debug_messaging_table->setHeader(array(
+    _('Escalation step'),
+    _('Time passed'),
+    _('Time'),
+	_('Action name'),
+	_('Escalation steps for op.'),
+	_('Operation'),
+	_('Media type'),
+	_('Alias'),
+	_('Send To'),
+	_('Error')
+));
+
+$command_table->setHeader(array(
+    _('Escalation step'),
+    _('Time passed'),
+    _('Time'),
+	_('Action name'),
+	_('Escalation steps for op.'),
+	_('Operation'),
+	_('Command'),
+	_('Type')
+));
+
+$debug_table->setHeader(array(
+	$link,
+	_('Action name'),
+	_('Eval type'),
+	_('Condition type'),
+	_('Operator'),
+	_('Condition Value'),
+	_('Trigger Value'),
+	_('Result')
+));
+
+if ($notifications) {
+    foreach ($notifications as $notification) {
+        //TODO: Process here
+        $notification_table->addRow(array(
+            'NI 1',
+            'NI 00:00:00',
+            'NI 13:00:00',
+            $notification['action_name'],
+            $notification['esc_step_from'].SPACE.'-'.SPACE.$notification['esc_step_to'],
+            $notification['opdesc'],
+            $notification['mediatypeid'],
+            $notification['alias'],
+            $notification['sendto']
+            ));
+    }
+}
+
+foreach ($debug_messaging as $row) {
+    $debug_messaging_table->addRow(array(
+        'NI 1',
+        'NI 00:00:00',
+        'NI 13:00:00',
+        $row['action_name'],
+        $row['esc_step_from'].SPACE.'-'.SPACE.$row['esc_step_to'],
+        $row['opdesc'],
+        $row['mediatypeid'],
+        $row['alias'],
+        $row['sendto'],
+        $row['error']
+    ));
+}
+
+foreach ($commands as $command) {
+    $command_table->addRow(array(
+        'NI 1',
+        'NI 00:00:00',
+        'NI 13:00:00',
+        $command['action_name'],
+        $command['esc_step_from'].SPACE.'-'.SPACE.$command['esc_step_to'],
+        $command['opdesc'],
+        $command['command'],
+        operation_scripttype2str($command['type'])
+    ));
+}
+
+//Preparation to using time from the form
+//TODO: Can't uncheck maintenance anymore
+//return mktime($hours, $minutes, 0, $month, $date, $year);
+    
+//At least one actions is active
+foreach ($debug as $row) {
+
+    //At least one condition is defined for the action
+    if (array_key_exists('conditions', $row)) {
+        foreach ($row['conditions'] as $condition) {
+            if ($condition['status'] == SUCCEED) {
+                //TODO: Seems to be swapped?
+                $status = new CSpan($condition['status'], 'off');
+            }
+            else {
+                $status = new CSpan($condition['status'], 'on');
+            }
+
+            //Host groups and templates are arrays
+            if (is_array($condition['actualvalue'])) {
+                $actualvalue = implode(', ', $condition['actualvalue']);
+            }
+            else {
+                $actualvalue = $condition['actualvalue'];
+            }
+
+            //TODO: Beautify
+            // Maintenance uses NULL, which looks weird in the debugging table
+            if ($condition['conditiontype'] == CONDITION_TYPE_MAINTENANCE) {
+                if ($condition['conditionvalue'] == '') {
+                    $condition['conditionvalue'] = HOST_MAINTENANCE_STATUS_ON;
+                }
+                else {
+                    $condition['conditionvalue'] = HOST_MAINTENANCE_STATUS_OFF;
+                }
+            }
+
+            $debug_table->addRow(array(
+                $link,
+                $row['name'],
+                action_evaltype2str($row['evaltype']),
+                condition_type2str($condition['conditiontype']),
+                condition_operator2str($condition['operator']),
+                $condition['conditionvalue'],
+                $actualvalue,
+                $status
+            ));
+        }
+    }
+    else {
+        // Actions without conditions always apply
+        $status = new CSpan('1', 'off');
+
+        $debug_table->addRow(array(
+            $link,
+            $row['name'],
+            action_evaltype2str($row['evaltype']),
+            '-',
+            '-',
+            '-',
+            '-',
+            $status
+        ));
+    }
+}
+
+$trigger_widget = new CUIWidget('trigger', $trigger_table);
+$trigger_widget->setHeader(_('Trigger details'));
+
+$notification_widget = new CUIWidget('notifications', $notification_table, 1, 1);
+$notification_widget->setHeader(_('Notifications'));
+
+$command_widget = new CUIWidget('commands', $command_table, 1, 1);
+$command_widget->setHeader(_('Remote Commands'));
+
+$mdebug_widget = new CUIWidget('messaging_debug', $debug_messaging_table, 0, 1);
+$mdebug_widget->setHeader(_('Notification mismatch'));
+
+$debug_widget = new CUIWidget('action_debug', $debug_table, 0, 1);
+$debug_widget->setHeader(_('Action condition matches'));
+
+$div = new CDiv(array($trigger_widget, $notification_widget, $mdebug_widget, $command_widget, $debug_widget), 'column');
+$frmAction->addRow($div);
+
+$frmAction->addItemToBottomRow(array(
+	new CSubmit('re_eval', _('Re-evaluate')),
+	new CButton('close', _('Close'),'javascript: self.close();')
+));
+$frmAction->Show();
+
+require_once dirname(__FILE__).'/include/page_footer.php';
