<?php
/**
 * App:
 *   main_menu = [menu safe name($_REQEST) => menu link name]
 *     is_allowed_menu() - checks if User can execute this menu (in array main_menu)
 *   functions like NEW_RECORD, EDIT_RECORD, UPDATEDB etc. not in MENU_INIT
 *   history: [menu => ]
 * 
 * [AJAX]
 *   print_js_ajax_callback
 *     js function definitions
 *   link_ajax( $name, $fun_name, $fun_args = array(), $attr = array() )
 *     create link to execute ajax function
 *   exec_ajax_request
 *     execute ajax request
 *   link_ajax_load_on_ready( $fun_name, $fun_args = array(), $attr = array() )
 *     load content from ajax request to function $fun_name
 *   TODO: ajax form creator
 *   TODO: ajax data table
 */

require_once dirname(__FILE__) . '/' . 'Lib.php';
Lib::loadClass('V');

class App {

/**
 * Generate URL-encoded query string.
 * @param $query - array or string
 */
public static function build_http_query( $query ) {
	$query_arr = array();// like in parse_url @see http://pl.php.net/manual/pl/function.parse-url.php
	$query_reserved_words = array('_scheme','_host','_user','_pass','_path','_query','_fragment');

	if (is_array($query)) {
		foreach ($query as $k => $v) {
			if (in_array($k, $query_reserved_words)) {
				$query_arr [substr($k, 1)] = $v;
			} else if ($k == '#') {
				$query_arr ['fragment'] = $v;
			} else {
				$query_arr ['query'][$k]= $v;
			}
		}//end foreach
	}
	else {
		$query_arr = parse_url($query);
		//	'http://uzytkownik:haslo@serwer/sciezka?arg=wartosc#kotwica'
		//	[scheme] => http
    //	[host] => serwer
		//	[user] => uzytkownik
		//	[pass] => haslo
		//	[path] => /sciezka
		//	[query] => arg=wartosc
		//	[fragment] => kotwica
		if (!empty($query_arr['query'])) {
			$query_arr_query = $query_arr['query'];
			parse_str($query_arr_query, $query_arr['query']);
		}
	}
	//	[scheme] => http
	//	[host] => serwer // $_SERVER['HTTP_HOST'] or SERVER_NAME @see http://stackoverflow.com/questions/2297403/http-host-vs-server-name
	//	[user] => uzytkownik
	//	[pass] => haslo
	//	[path] => /sciezka
	//	[query] => Array( arg=>wartosc, ... )
	//	[fragment] => kotwica

	// [scheme] -> require [host]
	// [user] -> require [host]
	// [pass] -> require [user],[host]
	// [path] -> require [host]
	// [query] -> 
	// [fragment] -> require [query]

	// App add task always
	if (!empty($query_arr['query'])) {
		if (empty($query_arr['query']['task'])) {
			if ($task = V::get('task', self::get_default_task(), $_REQUEST)) {
				$query_arr['query']['task'] = $task;
			}
		}
	}

	$href = '';
	if (!empty($query_arr['scheme'])) {
		$href .= $query_arr['scheme'].'://';
		// host is required if scheme
		if (empty($query_arr['host'])) $query_arr['host'] = $_SERVER['HTTP_HOST'];
	}
	if (!empty($query_arr['user'])) {// user:pass@server
		$href .= $query_arr['user'];
		if (!empty($query_arr['pass'])) $href .= ':'.$query_arr['pass'];
		$href .= '@';
		// host is required if user
		if (empty($query_arr['host'])) $query_arr['host'] = $_SERVER['HTTP_HOST'];
	}
	if (!empty($query_arr['host'])) $href .= $query_arr['host'];
	//$href .= (!empty($query_arr['path']))? $query_arr['path'] : $query_arr['PHP_SELF'];
	if (!empty($query_arr['path'])) $href .= $query_arr['path'];
	if (!empty($query_arr['query'])) {
		$tmp_query_arr = array();
		foreach ($query_arr['query'] as $k => $v) {
			if (is_array($v)) {
				if (strlen($k) < 3 || substr($k, -2) != '[]') {
					$k .= '[]';
				}
				foreach ($v as $v_arg_val) {
					$tmp_query_arr []= '' . $k . '=' . $v_arg_val;
				}//end foreach
			} else {
				$tmp_query_arr []= '' . $k . '=' . $v;
			}
		}//end foreach
		$href .= "?".implode("&", $tmp_query_arr);
	}
	if (!empty($query_arr['fragment'])) $href .= '#'.$query_arr['fragment'];

	return $href;
}

/**
 * @returns html link tag <a ... > ... </a>
 * @param $name
 * @param $href
 * @param $attr
 */
public static function link( $name, $href, $attr = array() ) {

	$out_href = App::build_http_query( $href );

	$txt = $name;
	$ico = V::get('ico', '', $attr);
	$ico_height = V::get('ico_height', 16, $attr, 'int');
	if (isset($attr['ico_height'])) unset($attr['ico_height']);
	if ($ico) {
		if (count(explode('.', $ico)) == 1) {
			$ico .= '.gif';// default ico format
		}
		if (file_exists( APP_PATH_ROOT . DS . 'icon' . DS . $ico )) {
			$txt = '<img src="'."icon/".$ico.'" height="'.$ico_height.'" alt="'.$name.'" />';
		}
		unset($attr['ico']);
	}
	$ico = V::get('ico_after_text', '', $attr);
	if ($ico) {
		if (count(explode('.', $ico)) == 1) {
			$ico .= '.gif';
		}
		if (file_exists( APP_PATH_ROOT . DS . 'icon' . DS . $ico )) {
			$txt .= ' <img src="'."icon/".$ico.'" height="'.$ico_height.'" alt="'.$name.'" />';
		}
		unset($attr['ico_after_text']);
	}

	$p_attr = array();
	if (!empty($attr)) {
		$p_attr_arr = array();
		foreach ($attr as $k => $v) {
			$p_attr_arr []= ''.$k.'="'.$v.'"';
		}//end foreach
		$p_attr []= ' '.implode(' ',$p_attr_arr);
	}
	$p_attr = (!empty($p_attr))? ' '.implode(' ', $p_attr) : '';

	return '<a href="'.$out_href.'"'.$p_attr.'>'.$txt.'</a>';
}

/**
 * @param $out_type - 'show', 'search'
 * @param $name - 
 * @param $sql_type - 
 * @param $value - 
 * @param $attr - 
 */
public static function _field( $out_type, $name, $sql_type, $value = '', $attr = array() ) {
	$ret = '';
	//$type = $_SESSION[$table_column]['TYPE'][$field];
	$type = $sql_type;
	//$name = $field;//$_SESSION[$table_column]['DESC'][ $_SESSION[$table_column]['DESC_TO_KEY'][$field] ];
	//if ($_SESSION['CURRENT_MENU']=='NEW_RECORD') $name = 'NEW_RECORD['.$name.']';

	// html tag
	$tag = new stdClass();
	$tag->name = '';
	$tag->attrs = '';
	$tag->cnt = null;

	// param attributes
	if (!empty($attr)) {
		foreach ($attr as $k_attr_name => $v_attr) {
			// parse param $k_attr_name
			switch ($k_attr_name) {
				case 'class': {
					$tag->attrs[$k_attr_name] []= $v_attr;
					break;
				}
				case 'style': {
					$attr_arr = array();
					foreach ($v_attr as $k_style => $v_style) {
						$attr_arr []= $k_style.'='.$v_style;
					}//end foreach
					$tag->attrs[$k_attr_name] []= $v_attr;
					break;
				}
				// TODO: ajax, etc
				default: {
					$tag->attrs[$k_attr_name] = $v_attr;
				}
			}
		}//end foreach
	}

	// size X -> style="width: Y px" : X=10 -> Y=75px, 1char=7,5px

	// parse type
	if (strstr($type, "enum")) {
		$tag->name = 'select';
		$tag->attrs['name'] = $name;
		$tag->attrs['id'] = $name;
		$tag->cnt = '<option value="%">'." [ Wybierz ] ".'</option>';

		$select_values = $type;
		$select_values = explode("(", $select_values);
		$select_values = end($select_values);
		$select_values = explode(")", $select_values);
		$select_values = reset($select_values);
		$select_values = explode(",", $select_values);
		sort($select_values);
		foreach ($select_values as $v) {
			$v = trim($v, "' ");//usuwa spacje i ' z poczatku i konca
			$max_length = 26;// TODO: param in @attr
			$sel = ($v == "$value")? ' selected="selected"' : '';
			$tag->cnt .= '<option value="'.$v.'"'.$sel.'>'.substr($v, 0, $max_length).' </option>';
		}
	}
	else if ((strstr($type, "char")) || (strstr($type, "int"))) {
		$tag->name = 'input';
		$max_length = $type;
		$max_length = explode("(",$max_length);
		$max_length = end($max_length);
		$max_length = explode(")",$max_length);
		$max_length = reset($max_length);
		$min_length = (strstr($type, "int"))? 4 : 10;// min length if empty value
		$tag->attrs['name'] = $name;
		$tag->attrs['type'] = 'text';
		$tag->attrs['id'] = $name;
		$tag->attrs['value'] = htmlspecialchars($value);// TODO: htmlspecialchars
		$tag->attrs['maxlength'] = $max_length;
		if (empty($tag->attrs['size'])) {
			$size = strlen($value) + 2;
			if ($size < $min_length) $size = $min_length;
			$tag->attrs['size'] = $size;
		}
		//$tag->attrs['style']['width'] = ceil($size * 7).'px';
	}
	else if (strstr($type, "datetime") || strstr($type, "date") || strstr($type, "timestamp")) {
		$max_length = $type;
		$max_length = end( explode("(", $max_length) );
		$max_length = reset( explode(")", $max_length) );
		$value = substr($value, 0, 10);
		$tag->name = 'input';
		$tag->attrs['name'] = $name;
		$tag->attrs['type'] = 'text';
		$tag->attrs['id'] = $name;
		$tag->attrs['value'] = $value;// TODO: htmlspecialchars
		$tag->attrs['maxlength'] = $max_length;
		if (empty($tag->attrs['size'])) $tag->attrs['size'] = 10;
		$tag->attrs['class'] []= 'date-pick';
	}
	else if (strstr($type, "double") || strstr($type, "float")) {
		$tag->name = 'input';
		$max_length = $type;
		$max_length = end( explode("(", $max_length) );
		$max_length = reset( explode(")", $max_length) );
		$value = substr($value, 0, 10);
		$tag->attrs['name'] = $name;
		$tag->attrs['type'] = 'text';
		$tag->attrs['id'] = $name;
		$tag->attrs['value'] = $value;// TODO: htmlspecialchars
		$tag->attrs['maxlength'] = $max_length;
		if (empty($tag->attrs['size'])) $tag->attrs['size'] = 6;// TODO: param in @attr
	}
	else if (strstr($type, "text")) {
		if ($out_type == 'search') {
			$tag->name = 'input';
			$tag->attrs['name'] = $name;
			$tag->attrs['id'] = $name;
			$tag->attrs['maxlength'] = 255;
			$tag->attrs['value'] = $value;// TODO: htmlspecialchars
		} else {
			$tag->name = 'textarea';
			$tag->attrs['name'] = $name;
			$tag->attrs['id'] = $name;
			if (empty($tag->attrs['rows'])) $tag->attrs['rows'] = 5;// TODO: param in @attr
			if (empty($tag->attrs['cols'])) $tag->attrs['cols'] = 70;// TODO: param in @attr
			$tag->cnt = $value;// TODO: htmlspecialchars
		}
	}
	else if ('typespecial_' == substr($type, 0, 12)) {
		if (!function_exists($type)) {
			echo'<p class="red">'."Typespecial function '".substr($type, 12)."' not exists!".'</p>';
		} else {
			return $type( $name, $out_type, $value, $attr );
		}
	}
	else {
		//$ret .= "UNKNOWN $type";
	}

	$ret = '';
	if ($tag->name) {

		// attributes with array values - like class
		if (empty($tag->attrs)) {
			$tag->attrs = '';
		} else {
			$attr_arr = array();
			foreach ($tag->attrs as $k_attr_name => $v_attr) {
				switch ($k_attr_name) {
					case 'class': {
						$v_attr = implode(' ', $v_attr);
						break;
					}
					case 'style': {
						$style_attr_arr = array();
						foreach ($v_attr as $k_style => $v_style) {
							$style_attr_arr []= ''.$k_style.':'.$v_style;
						}//end foreach
						$v_attr = implode(';', $style_attr_arr);
						break;
					}
					default: {
						//
					}
				}
				$attr_arr []= $k_attr_name.'="'.$v_attr.'"';
			}//end foreach

			$tag->attrs = ' '.implode(' ', $attr_arr);
		}

		// tag style
		if ($tag->cnt !== null) {
			$ret .= '<'.$tag->name.$tag->attrs.'>'.$tag->cnt.'</'.$tag->name.'>';
		} else {
			$ret .= '<'.$tag->name.$tag->attrs.' />';
		}
	}
	return $ret;
}

public static function field( $name, $sql_type, $value = '', $attr = array() ) {
	return self::_field( 'show', $name, $sql_type, $value, $attr );
}

public static function field_search( $name, $sql_type, $value = '', $attr = array() ) {
	return self::_field( 'search', $name, $sql_type, $value, $attr );
}

public static function set_function_init_output( $cnt ) {
	self::set_state('function_init_output', $cnt);
}
public static function get_function_init_output() {
	return self::get_state('function_init_output');
}
public static function exec_function_init() {
	if (($fun_init = V::get('function_init', '', $_REQUEST)) != '') {
		ob_start();
		if (function_exists( $fun_init )) {
			$fun_init();
		} else {
			echo'<p class="err">'."function_init not exists!".'</p>';
		}
		$cnt = ob_get_contents();
		ob_clean();
		self::set_function_init_output( $cnt );
	}
}

public static function quit() {
	App::set_state( 'quit', true );
}
public static function is_quit() {
	return App::get_state( 'quit' );
}
public static function set_default_task( $default_task ) {
	self::set_state('default_task', $default_task);
}
public static function get_default_task() {
	return self::get_state('default_task');
}
public static function get_task() {
	$default_task = self::get_default_task();
	$task = V::get('task', $default_task, $_GET);
	return $task;
}
public static function exec_task() {
	self::show_msgs();

	echo "\n".'<div class="function_init_output">'."\n";
		echo self::get_function_init_output();
	echo "\n".'</div>'."\n";

	if (self::is_quit()) {
		return;
	}

	$default_task = self::get_default_task();
	if ($task = V::get('task', $default_task, $_GET)) {
		$task_fun = 'task_'.$task;
		if (function_exists($task_fun)) {
			echo "\n".'<div id="body_content">'."\n";
				$task_fun();
			echo "\n".'</div>'."\n";
		} else {
			echo'<p class="err">'."Wrong task!".'</p>';
		}
	}
}

public static function show_msgs() {
	$msgs_all = self::get_msgs();
	if (!empty($msgs_all)) {
		foreach ($msgs_all as $msg_type => $msgs) {
			echo "\n".'<div class="app-msgs app-msg-type-'.$msg_type.'">'."\n";
			echo implode('<br />', $msgs);
			echo "\n".'</div>'."\n";
		}//end foreach
	}
}

public static function print_js_ajax_callback() {
	static $_showed;
	if (!$_showed) {
		echo"\n".'<script type="text/javascript">'."
// linkPopup - jQuery plugin
(function($){
$.fn.linkPopup = function(event){

function showPopup(trigger,popup,e){
	var et = e.pageY,
	el = e.pageX,
	//p = popup.height(),
	pw = 700,
	ph = 400,// ~ height auto
	ww = $(window).width(),
	wh = $(window).height(),
	ws = $(window).scrollTop(),
	// X center over mouse, Y 20 up
	pos_left = e.pageX - pw/2,
	pos_top = e.pageY - 20,
	popup_wrap=popup.parent();
	// show all popup
	if (pos_left + pw > ww) { pos_left = ww - pw - 20; }
	else if (pos_left < 0) { pos_left = 10; }
	if (pos_top + ph > ws + wh) { pos_top = ws + wh - ph; }
	else if (pos_top < ws) { pos_top = ws; }
	//pos_top = (et + p) > (s + wh) ? (s + wh - p) : et - 10,

	//if (popup.text() === '') {
	if (true) {
		// empty
		console.log('popup empty');
		console.log(trigger.attr('href'))

		jQuery.ajax({
			type: 'GET',
			url: trigger.attr('href'),
			success: function(data){
				//console.log(data);
				popup.html(data)

				popup_wrap.css({width: pw, top: pos_top, left: pos_left, height: ph});// width and height
				//popup_wrap.css({top: pos_top, left: pos_left});
				popup_wrap.fadeIn(100);
			}
		});
	}else{
		console.log('popup full');

		popup_wrap.css({width: pw, top: pos_top, left: pos_left, height: ph});// width and height
		//popup_wrap.css({top: pos_top, left: pos_left});
		popup_wrap.fadeIn(100);
	}
}

return this.each(function(){
var trigger = $(this), timer, popup = null, popup_wrap=null;//$(this).next();
popup = jQuery('#tip-popup-box');
// create div if not exists ('#tip-popup-box')
//if (!popup.hasClass('tip-popup-box'))
if(popup.length==0){
	//console.log('Error popup not found, creating...')
	popup = jQuery('<div></div>')
	popup.attr('id', 'tip-popup-box')
	popup.text('')
	jQuery('body').append(popup);// popup.insertAfter(trigger);
	console.log('created')

	console.log('wrap popup...')
	popup.wrap('<div></div>')
	popup_wrap=popup.parent()
	popup_wrap.addClass('tip-popup-wrap')
	popup_wrap.css('display', 'none')
	jQuery('<div class=\"title\"><button class=\"btn_close\">X</button></div>').insertBefore(popup)
	console.log('wrap popup end')
}else{
	popup_wrap=popup.parent()
}

//console.log(trigger.attr('id'));
trigger.attr('onclick','return false;')
trigger.click(function(e){
	clearTimeout(timer);
	timer = setTimeout(function(){ showPopup(trigger,popup,e); }, 500);
});
//popup.bind('mouseleave', function(){
//	trigger.removeClass('active');
//	clearTimeout(timer);
//	timer = setTimeout(function(){ popup.fadeOut(50); }, 500);
//})

// dont close after click on popup - TODO: X (close btn)
popup_wrap.find('.btn_close').bind('click', function(){
	trigger.removeClass('active');
	clearTimeout(timer);
	timer = setTimeout(function(){ popup_wrap.fadeOut(50); }, 500);
});

	// execute click on init:
	clearTimeout(timer);
	timer = setTimeout(function(){ showPopup(trigger,popup,event); }, 500);
});
};
})(jQuery);


function procesy_ajax_link(l, result_type, result){
	return procesy_ajax_run(l, l.href, result_type, result);
}
function insertAfter(parent, n, referenceNode) {
  parent.insertBefore(n, referenceNode.nextSibling);
}
function procesy_ajax_run(l, href, result_type, result){
	var img = jQuery('<img src=\"./stuff/i/loading.gif\" alt=\"loading\" />');
	l.parentNode.appendChild(img.get(0));//img.insertAfter(l);
	var res = null;
	if(result_type == 'id'){
		res = jQuery('#' + result).get(0);
	}else if(result_type == 'after'){
		res = document.createElement('div');
		insertAfter(l.parentNode, res, l);//res.insertAfter(l);
	}else if(result_type == 'override'){
		res = l;
		//insertAfter(l.parentNode, res, l);//res.insertAfter(l);
	}else if(result_type == 'override_parent'){
		res = l.parentNode;
		//insertAfter(l.parentNode, res, l);//res.insertAfter(l);
	}else if(result_type == 'popup'){
		// TODO: create or get windows object if already exists
		//var document.createElement('div');
		// TODO: add res to body at the end! popup z sew (SewView)
		//jQuery(l).linkPopup();
try{
		jQuery(l).linkPopup(window.event);// create window with link href to put into window
}catch(e){
	console.log('e...')
	console.log(e)
}
		jQuery(img).remove();
		return false;
	}
	if(!res){
		console.log('error: no res!');
		return false;
	}
	jQuery.ajax({
		type: 'GET',
		url: href,
		success: function(data){
			//console.log(data);
			if(result_type == 'after') {
				//jQuery(data).insertAfter(l);
				res.innerHTML = data;
			}else if(result_type == 'override'){
				//jQuery(data).insertAfter(l);
				//res.innerHTML += data;
				//jQuery(res).append(data)
				jQuery(res).after(data);
				jQuery(l).remove();
				//res.parentNode.removeChild(l)
			}else if(result_type == 'override_parent'){
				//jQuery(data).insertAfter(l);
				//res.innerHTML += data;
				//jQuery(res).append(data)
				jQuery(res).after(data);
				jQuery(l.parentNode).remove();
				//res.parentNode.removeChild(l)
			}else if(result_type == 'popup'){
				//res.html(data)
try{
				//var link_popup=jQuery(l).linkPopup();// create window
				var link_popup=jQuery(l).linkPopup(data);// create window and put data into window
				//link_popup.setData(data);// put data into window
				jQuery(l).click();
}catch(e){
	console.log('e...')
	console.log(e)
}
			}
			jQuery(img).remove();
		}
	});
	return false;
}


jQuery(document).ready(function(){
	jQuery('.ajax_load_on_ready').each(function(index, l){
		// html - replace contetn
		l.innerHTML += ' <img src=\"./stuff/i/loading.gif\" alt=\"loading\" />';
		// append
		jQuery.ajax({
			type: 'GET',
			url: l.href,
			success: function(data){
				jQuery(data).insertAfter(l);
				jQuery(l).remove();
			}
		});
	});
});


// lightbox, TODO: init after ajax
jQuery(function() {
	$('a.lightbox').each(function(){
		jQuery(this).lightBox({
			overlayBgColor:'#000',
			overlayOpacity:0.7,
			imageLoading:  'stuff/i/loading.gif', // (string) Path and the name of the loading icon
			imageBtnPrev:  'stuff/i/prev.gif',    // (string) Path and the name of the prev button image
			imageBtnNext:  'stuff/i/next.gif',    // (string) Path and the name of the next button image
			imageBtnClose: 'stuff/i/del.png',   // close.gif (string) Path and the name of the close btn
			imageBlank:    'stuff/i/blank.gif',   // (string) Path and the name of a blank image (one pixel)
			containerResizeSpeed:350,
			showImageData:false, // show image data?
			txtImage:'Obrazek',
			txtOf:'z'
		});
	});
});


function scrollToProces(item_id) {
	var el=jQuery('#TREE'+item_id);
	el.parents('.close').removeClass('close');// open all closed elements
	if (!el.length) {
		alert(item_id + ' prawdopodbnie nie istnieje.');
	} else {
		el.scrollintoview({
			duration: 'fast',
			direction: 'vertical',
			complete: function() {
				el.addClass('active');
			}
		});
	}
	return false;
}

		".'</script>'."\n";
		$_showed = true;
	}
}

/**
 * @returns html ajax link tag <a ... > ... </a>
 * @param $name
 * @param $href
 * @param $attr
 */
public static function link_ajax( $name, $fun_name, $fun_args = array(), $attr = array() ) {
	// TODO: where to store ajax result: after, id, function
	// TODO: App::print_js_ajax_callback()

	$txt = $name;

	$ico = V::get('ico', '', $attr);
	$ico_height = V::get('ico_height', 16, $attr, 'int');
	if (isset($attr['ico_height'])) unset($attr['ico_height']);
	if ($ico) {
		if (count(explode('.', $ico)) == 1) {
			$ico .= '.gif';// default ico format
		}
		if (file_exists( APP_PATH_ROOT . DS . 'icon' . DS . $ico )) {
			$txt = '<img src="'."icon/".$ico.'" height="'.$ico_height.'" alt="'.$name.'" />';
		}
		unset($attr['ico']);
	}
	$ico = V::get('ico_after_text', '', $attr);
	if ($ico) {
		if (count(explode('.', $ico)) == 1) {
			$ico .= '.gif';
		}
		if (file_exists( APP_PATH_ROOT . DS . 'icon' . DS . $ico )) {
			$txt .= ' <img src="'."icon/".$ico.'" height="'.$ico_height.'" alt="'.$name.'" />';
		}
		unset($attr['ico_after_text']);
	}

	$js_fun_attr = array();
	$js_fun_attr['result_type'] = V::get('js_result_type', 'node', $attr);
	$js_fun_attr['result'] = V::get('js_result', 'after', $attr);
	unset($attr['js_result_type']);
	unset($attr['js_result']);
	$js = "return procesy_ajax_link(this, '".$js_fun_attr['result_type']."', '".$js_fun_attr['result']."');";
	$attr['onclick'] = $js;
	$p_attr = array();
	if (!empty($attr)) {
		$p_attr_arr = array();
		foreach ($attr as $k => $v) {
			$p_attr_arr []= ''.$k.'="'.$v.'"';
		}//end foreach
		$p_attr []= implode(' ',$p_attr_arr);
	}
	$p_attr = (!empty($p_attr))? ' '.implode(' ', $p_attr) : '';

	$href_args = array();
	$href_args []= "_ajax_request=".$fun_name;
	foreach ($fun_args as $k => $v) {
		$href_args []= "$k=$v";
	}//end foreach
	$out_href = "?" . implode("&", $href_args);

	return '<a href="'.$out_href.'"'.$p_attr.'>'.$txt.'</a>';
}
/*
 * link_ajax_load_on_ready( $fun_name, $fun_args = array(), $attr = array() )
 *   load content from ajax request to function $fun_name
 */
public static function link_ajax_load_on_ready( $name, $fun_name, $fun_args = array(), $attr = array() ) {
	// TODO: where to store ajax result: after, id, function
	// TODO: App::print_js_ajax_callback()
	$js = "return procesy_ajax_link(this, 'override', 'node');";
	$attr['onclick'] = $js;
	$attr['class'] = 'ajax_load_on_ready';
	$p_attr = array();
	if (!empty($attr)) {
		$p_attr_arr = array();
		foreach ($attr as $k => $v) {
			$p_attr_arr []= ''.$k.'="'.$v.'"';
		}//end foreach
		$p_attr []= implode(' ',$p_attr_arr);
	}
	$p_attr = (!empty($p_attr))? ' '.implode(' ', $p_attr) : '';

	$href_args = array();
	$href_args []= "_ajax_request=".$fun_name;
	foreach ($fun_args as $k => $v) {
		$href_args []= "$k=$v";
	}//end foreach
	$out_href = "?" . implode("&", $href_args);

	$txt = $name;

	return '<a href="'.$out_href.'"'.$p_attr.'>'.$txt.'</a>';
}

	// ?_ajax_request=FUNCTION
	public static function exec_ajax_request() {
		if (($ajax_request_fun = V::get('_ajax_request', '', $_REQUEST)) != '') {
			// TODO: SEF( $ajax_request_fun )
			if (function_exists($ajax_request_fun)) {
				//sleep(1);
				if ( User::logged() ) {
					$ajax_request_fun();
				} else {
					sleep(1);
					header("HTTP/1.0 401 Unauthorized");
				}
			} else {
				sleep(1);
				header("HTTP/1.0 404 Not Found");
			}
			die();
		}
	}

public static function show_head_css() {
	echo '<link rel="stylesheet" type="text/css" href="stuff/jquery-ui-smoothness/jquery-ui-1.10.1.custom.min.css">' . "\n";
	echo '<style type="text/css">'."
.tip-popup-wrap{display:none;padding:0;position:absolute;z-index:10000;background:#fff;border:4px solid #444;}
.tip-popup-wrap #tip-popup-box{margin:0;padding:3px;background:#fff;color:#000;text-align:left;overflow:auto;}
.tip-popup-wrap .title{margin:0;background:#444;color:#fff;line-height:20px;font-weight:bold;text-align:right;}
.tip-popup-wrap .title h3{margin:0;padding:0;border-bottom:1px solid #ccc;background:#999;color:#fff;font-weight:bold;}

.app-msgs{margin:3px 10px;padding:4px;border:1px solid #666;}
.app-msg-type-msg{boder-color:#008000;background:#CEFFCE;}
.app-msg-type-err{boder-color:#FF0000;background:#FFB8B8;}

/* lightbox */
#jquery-overlay { width:100%; height:500px; position:absolute; top:0; left:0; z-index:90; }
#jquery-lightbox { width:100%; position:absolute; top:0; left:0; z-index:100; text-align:center; line-height:0; }
#jquery-lightbox img { border:none; }
#lightbox-container-image-box { width:250px; height:250px; margin:0 auto; position:relative; background-color:#fff; }
#lightbox-container-image { padding:10px; }
#lightbox-loading { position:absolute; top:40%; left:0%; height:25%; width:100%; text-align:center; line-height:0; }
#lightbox-nav { position:absolute; top:0; left:0; height:100%; width:100%; z-index:10; }
#lightbox-container-image-box > #lightbox-nav { left:0; }
#lightbox-nav a { outline:none;}
#lightbox-nav-btnPrev,
#lightbox-nav-btnNext { display:block; width:49%; height:100%; zoom:1; }
#lightbox-nav-btnPrev { float:left; left:0; }
#lightbox-nav-btnNext { float:right; right:0; }
#lightbox-container-image-data-box { width:100%; overflow:auto; margin:0 auto; padding:0 10px 0; font:10px Helvetica, sans-serif; background-color:#fff; line-height:1.4em; }
#lightbox-container-image-data { padding:0 10px; color:#666; }
#lightbox-container-image-data #lightbox-image-details { float:left; width:70%; text-align:left; }
#lightbox-image-details-caption { font-weight:bold; }
#lightbox-image-details-currentNumber { display:block; clear:left; padding-bottom:1.0em; }
#lightbox-secNav-btnClose { float:right; width:66px; padding-bottom:0.7em; }

.DEBUG_S {display:none;}
body.show-DEBUG_S .DEBUG_S {display:block;}
	".'</style>' . "\n";
}
public static function show_head_js() {
	//echo '<script type="text/javascript" src="stuff/jquery.js"></script>'."\n";
	echo '<script type="text/javascript" src="stuff/jquery-ui.custom.min.js"></script>' . "\n";
//	echo '<script type="text/javascript" src="stuff/jquery-ui.custom.js"></script>' . "\n";
	echo '<script type="text/javascript" src="stuff/jquery.lightbox-0.5.js"></script>'."\n";
	echo '<script type="text/javascript" src="stuff/jquery.scrollintoview.min.js"></script>'."\n";
	echo self::print_js_ajax_callback();
}

	public static function ui_widget($type, $title, $msg = '') {
		$ico_types = array('check', 'info', 'alert');
		$ui_states = array('check' => 'highlight', 'info' => 'highlight', 'alert' => 'error');
		$ico = (in_array($type, $ico_types))? '<span class="ui-icon ui-icon-' . $type . '" style="float:left; margin-right:.3em;"></span>' : '';
		$ui_state = V::get($type, 'highlight', $ui_states);
		$out .= '<div class="ui-widget">';
			$out .= '<div class="ui-state-' . $ui_state . ' ui-corner-all" style="margin-top:20px; padding:0 .7em;">';
				$out .= '<p>' . $ico;
				if ($type == 'alert') {
					$out .= '<strong>' . "Error: " . '</strong>' . $title;
				} else {
					$out .= '<strong>' . $title . '</strong>';
				}
				echo '</p>';
				if (!empty($msg)) {
					$out .= '<p>' . $msg . '</p>';
				}
			$out .= '</div>';
		$out .= '</div>';
		return $out;
	}

/**
 * authorize user
 * TODO: use PROCES_AUTH
 *   CRM_AUTH_PROFILE - select all where found login and passwd in REMOTE_TABLE REMOTE_ID
 * TODO: prevent ajax request - return 404???
 */
public static function auth() {
	$LOGIN = V::get('LOGIN', '', $_REQUEST);

	Lib::loadClass('User');
	if ( ! User::logged() ) {
		if ($LOGIN == 'LOGIN') {
			SEF('AUTHORIZE_USER_LOGIN');

			$ADM_ACCOUNT = V::get('ADM_ACCOUNT', '', $_REQUEST);
			$ADM_PASSWD = V::get('ADM_PASSWD', '', $_REQUEST);
			AUTHORIZE_USER_LOGIN( $ADM_ACCOUNT, $ADM_PASSWD );
		}
	}

	if ( User::logged() ) {
		if ($LOGIN == 'LOGOUT') {
			echo "Wylogowano,<br><img src='superedit-software-640.jpg'> 
				<a href='".$_SERVER['PHP_SELF']."'>*LOGOWANIE* </a>";
			session_destroy();
			die();
		}
	}

	if ( ! User::logged() ) {
		echo "<img src='superedit-software-640.jpg'>by A.Binder arek@tx.pl<br><h2><a href='".$_SERVER['PHP_SELF']."'>*Wersja testowa WWW </a> (szyfrowanieSSL)</h2>
<br>narazie przez interfejs WWW:
 <li>Wylacznie usuwanie problemow (kosztowe i bezkosztowe)
 <li>Drukowanie istniejacych w bazie problemow (z ekranu)
 <li>Baza uzytkownikow do edycji
 <li>Historia uzytkownika
 <li>Edycja statusow i udostepnionych pol
 <li>Szybkie filtry
 <li>Rozdzielenie preferencji dostepow na uzytkownikow 
 <li>Inne opcje
 <li>Wkrotce wszystkie opcje z wersji terminalowej SUPEREDIT



  
<hr>Musisz sie zautoryzowac<br>

   <FORM NAME='LOGIN' ACTION='".$_SERVER['PHP_SELF']."' METHOD='POST'>Uzytkownik:<INPUT TYPE=TEXT NAME='ADM_ACCOUNT' VALUE='' id='username'><br>
   Haslo:<INPUT TYPE=PASSWORD NAME='ADM_PASSWD'><INPUT NAME='LOGIN' TYPE=SUBMIT VALUE='LOGIN'></FORM></BODY></HTML>
   ";
echo'<script type="text/javascript">'."
function init(){
  // quit if this function has already been called
  if (arguments.callee.done) return;
  // flag this function so we don't do the same thing twice
  arguments.callee.done = true;

	document.getElementById('username').focus();
}
// on load function
if (document.addEventListener) {
  document.addEventListener('DOMContentLoaded', init, false);
} else {
	window.onload = init;
}
".'</script>';
		die();
	} else if ($LOGIN == 'SHOW') {
		echo "Jestes zalogowany jako ".$_SESSION['ADM_NAME']." (<a href='".$_SERVER['PHP_SELF']."?USEREDIT=VIEW'>".$_SESSION['AUTHORIZE_USER']."</a>) 
		<a href='".$_SERVER['PHP_SELF']."?LOGIN=LOGOUT'>Wyloguj</a> |
		<form action='".$_SERVER['PHP_SELF']."' method='POST'>
		ZMIEN STARE HASLO:<INPUT TYPE=PASSWORD NAME='ADM_PASSWD'>  NOWE HASLO:<INPUT TYPE=PASSWORD NAME='ADM_PASSWD_NEW'><INPUT NAME='LOGIN' TYPE=SUBMIT VALUE='PASSEDIT'>
		</form><br>";
	} else if ($LOGIN == 'PASSEDIT') {
		$ZAP_SQL="update `ADMIN_USERS` set `ADM_PASSWD`=md5('".$_POST['ADM_PASSWD_NEW']."') where `ADM_ACCOUNT`='".$_SESSION['AUTHORIZE_USER']."' and ( `ADM_PASSWD`='".$_POST['ADM_PASSWD']."' or `ADM_PASSWD`=md5('".$_POST['ADM_PASSWD']."')) limit 1; ";
		echo " Zmieniam haslo dla ".$_SESSION['AUTHORIZE_USER']."  <br>";
		DB::query( $ZAP_SQL );
  }
}

/**
 * object state
 */
public static function get_state($k) {
	return self::state('get', $k);
}
public static function set_state($k, $v) {
	return self::state('set', $k, $v);
}
public static function state($task, $k, $v = null) {
	static $state;
	if (!$state) $state = array();

	if ($task == 'set') {
		$state [$k] = $v;
	} else if ($task == 'get') {
		if (array_key_exists($k, $state)) {
			return $state[$k];
		} else {
			$null = null;
			return $null;
		}
	} else {
		// TODO: err
	}
}

/**
 * Fetch all messages and remove from queue.
 */
public static function get_msgs() {
	$ret = array();
	if (!empty($_SESSION['app-msgs'])) {
		foreach ($_SESSION['app-msgs'] as $msg_type => $msgs) {
			$ret [$msg_type] = $msgs;
		}//end foreach
		$_SESSION['app-msgs'] = array();
	}
	return $ret;
}

/**
 * Add message to app message queue.
 * @see show_msgs
 */
public static function add_error($msg = '') {
	self::_add_msg($msg, 'err');
}
public static function add_msg($msg = '') {
	self::_add_msg($msg, 'msg');
}
public static function _add_msg($msg = '', $type = 'msg') {
	if ($msg) {
		$_SESSION['app-msgs'] [$type] []= $msg;
	}
}

public static function redirect($url, $msg = '') {
	if ($msg) {
		self::add_msg($msg);
	}

	if (!headers_sent()) {
		header('HTTP/1.1 303 See Other');
		header('Location: '.$url);
	} else {
		echo'<script type="text/javascript">'."
window.location.href='".$url."';
		".'</script>';
		echo "\n".'<noscript>';
		echo "\n".'<meta http-equiv="refresh" content="0;url='.$url.'" />';
		echo "\n".'</noscript>';
		echo'<p>'.'<a href="'.$url.'">'."dalej".'</a>'.'</p>';
	}
	exit;
}

	public static function is_ajax_request() {
		if (array_key_exists('X_REQUESTED_WITH', $_SERVER)) {
			$index = 'X_REQUESTED_WITH';
		}
		else {
			$index = 'HTTP_X_REQUESTED_WITH';
		}
		$is_xml_http_request = array_key_exists($index, $_SERVER) && $_SERVER[$index] == 'XMLHttpRequest';
		return $is_xml_http_request;
	}

}
