/*container for widgets*/
widget_display = gw_new_container();
widget_display.on_event = function(evt) 
{
 if(!widget_display.children.length) return false;
 return widget_display.children[widget_display.children.length-1].on_event(evt);
}

widget_tool_size = 18;
widget_min_size = 5*widget_tool_size;
widget_default_size = 100;


function check_widget_display(width, height) 
{
	var count = WidgetManager.num_widgets;
	for (var i=0; i<count; i++) {
	  var x, y;
		var wid = WidgetManager.get(i);
		if (wid == null) continue;
		if (!wid.visible) continue;
		
	  x = wid.x;
    y = wid.y;
		if (x-wid.width/2 <= -width/2) x = wid.width/2-width/2;
		else if (x+wid.width/2 >= width/2) x = width/2 - wid.width/2;
		
		if (y + wid.height/2 >= height/2) y = height/2 - wid.height/2;
		else if (y  - wid.height/2 <= - height/2) y = -height/2 + wid.height/2;

		if (wid.widget_control) wid.widget_control.move(x, y);
	}
}

function scan_directory(dir)
{
	var i, j, count, list, new_wid, uri;
	list = gpac.enum_directory(dir, '.xml;.wgt;.mgt', 0);
	for (i=0; i<list.length; i++) {
		uri = list[i].path + list[i].name;
		if (list[i].directory) {
			scan_directory(uri);
		} else {
			count = WidgetManager.num_widgets;
			for (j=0; j<count; j++) {
				var wid = WidgetManager.get(j);
				if (wid.url==uri) break;
			}
			if (j==count) {
				new_wid = WidgetManager.open(uri, null);
				if (new_wid!=null) {
					widget_insert_icon(new_wid);
				}
			}
		}
	}
}

widman_cfg_dlg = null; 

function open_widget_manager(extension)
{
  if (widman_cfg_dlg) return;
  
  widman_cfg_dlg = gw_new_window_full(null, true, 'Widget Manager', 'window');  
  widman_cfg_dlg.area = gw_new_grid_container(widman_cfg_dlg);
  var icon = gw_new_icon_button(widman_cfg_dlg.area, gwskin.images.add, 'Add widget', 'button');
  icon.on_click = function() {
    widman_cfg_dlg.close();
    widman_cfg_dlg = null;
    
    var filebrowse = gw_new_file_open();
    filebrowse.show_directory = true;
    filebrowse.filter = '*.xml;*.wgt;*.mgt';
    filebrowse.browse(WidgetManager.last_widget_dir);  
  
    filebrowse.on_browse = function(value, directory) {
  		var new_wid = WidgetManager.open(value, null);
	  	if (new_wid==null) return;
		  WidgetManager.last_widget_dir = directory;
		  widget_insert_icon(new_wid);
		  dock.layout(dock.width, dock.height);
		  show_dock(true);
    }
    filebrowse.on_directory = function(directory) {
  		WidgetManager.last_widget_dir = directory;
   		scan_directory(directory);
		  show_dock(true);
    }
    filebrowse.set_size(320 , 240);
    gpacui_show_window(filebrowse);
  }
  var icon = gw_new_icon_button(widman_cfg_dlg.area, gwskin.images.trash, 'Remove all widgets', 'button');
  icon.on_click = function() {
		while (1) {
			var wid = WidgetManager.get(0);
			if (wid==null) break;
			widget_remove(wid);
		}
    widman_cfg_dlg.close();
    widman_cfg_dlg = null;
	  dock.layout(dock.width, dock.height);
	  show_dock(true);
  }
  widman_cfg_dlg.on_close = function() {
   widman_cfg_dlg = null;
  }
  widman_cfg_dlg.set_size(320 , 240);
  gpacui_show_window(widman_cfg_dlg);
}

function widget_insert_icon(new_wid) {
	//var icon = gw_new_icon_button(dock, widget_get_icon(new_wid), new_wid.name, 'button');
	var icon = gpacui_insert_dock_icon(new_wid.name, widget_get_icon(new_wid) );
	new_wid.in_panel = true;
	new_wid.visible = false;
	new_wid.icon_dock = icon;
	icon.on_click = on_widget_launch;
	icon.widget = new_wid;
}

function collapsable_list(info_dlg, title)
{
	var info = gw_new_button(info_dlg.area, title, 'button');
	var children = info_dlg.area.get_children();
	
	info.first_idx = children.length;
	info.dlg = info_dlg;
	info.displayed = true;
  info.on_click = function() {
   var children = this.dlg.area.get_children();
   this.displayed = !this.displayed;
	 for (var i=this.first_idx; i<this.last_idx; i++) {
    if (this.displayed) children[i].show();
    else children[i].hide();
  	
    if (typeof children[i].last_idx != 'undefined') {
      if (!children[i].displayed) children[i].on_click();
     }
   }
   this.dlg.area.layout_changed();
  }
  return info;
}

//widget information dialog
function display_widget_info(wid)
{
	var i, j, k, info;
	var y, txt, pref;

	var info_dlg = gw_new_window_full(null, true, 'Widget ' + wid.name + ' Information', 'window', null);
//  info_dlg.area = gw_new_grid_container(info_dlg);
  info_dlg.area = gw_new_listbox(info_dlg);
 
	var info = collapsable_list(info_dlg, 'Widget Metadata');
	
  gw_new_text(info_dlg.area, 'id: ' + wid.identifier + ' - shortname: '+wid.shortName + ' - name: '+wid.name, 'text');
  gw_new_text(info_dlg.area, 'version: '+wid.version, 'text');
  gw_new_text(info_dlg.area, 'content type: ' + wid.mainMimeType + ' - content encoding: '+wid.mainEncoding, 'text');
  gw_new_text(info_dlg.area, 'default size: Width = ' + wid.defaultWidth + ' Height = '+wid.defaultHeight, 'text');
  gw_new_text(info_dlg.area, 'license: '+wid.license, 'text');
  gw_new_text(info_dlg.area, 'license ref: '+wid.licenseHref, 'text');
  gw_new_text(info_dlg.area, 'description: '+wid.description, 'text');
  gw_new_text(info_dlg.area, 'author name: '+wid.authorName + ' (mail: '+wid.authorEmail+')', 'text');
  gw_new_text(info_dlg.area, 'author href: '+wid.authorHref, 'text');
  gw_new_text(info_dlg.area, 'view modes: '+wid.viewmodes, 'text');
  gw_new_text(info_dlg.area, 'UUID: '+wid.uuid, 'text');
  gw_new_text(info_dlg.area, 'Discardable: '+wid.discardable, 'text');
  gw_new_text(info_dlg.area, 'Muliple Instances: '+wid.discardable, 'text');
	var icons = wid.icons;
	for (j=0; j<icons.length; j++) {
    gw_new_text(info_dlg.area, 'Icon #'+(j+1)+': ' + icons[j].src, 'text');
	}
	info.last_idx = info_dlg.area.get_children().length;
	info.on_click();

	info = collapsable_list(info_dlg, 'Widget Manager Info');

	gw_new_text(info_dlg.area, 'nb instances: '+wid.num_instances + ' nb components: '+wid.num_components, 'text' );
	gw_new_text(info_dlg.area, 'Permanently installed: '+wid.permanent + ' - is component: '+wid.is_component, 'text' );
	if (wid.is_component) {
		gw_new_text(info_dlg.area, 'parent widget name' + wid.parent.name, 'text');
	}
	if (wid.originating_device_ip) {
		gw_new_text(info_dlg.area, 'Widget was pushed from device IP '+wid.originating_device_ip, 'text' );
	}
	gw_new_text(info_dlg.area, 'Section name in GPAC config file: '+wid.section, 'text' );
	gw_new_text(info_dlg.area, 'UA Locale: ' + gpac.getOption('Systems', 'LanguageName') + ' ('+ gpac.getOption('Systems', 'Language2CC')+ ')', 'text' );
	gw_new_text(info_dlg.area, 'widget src: ' + wid.url , 'text');
	gw_new_text(info_dlg.area, 'config src: ' + wid.manifest , 'text');
	gw_new_text(info_dlg.area, 'content src : '+wid.localizedSrc, 'text' );
	info.last_idx = info_dlg.area.get_children().length;
	info.on_click();

	pref = wid.features;
	if (pref.length) {
  	info = collapsable_list(info_dlg, 'Features');
  	for (j=0; j<pref.length; j++) {
  		gw_new_text(info_dlg.area, 'Feature #'+(j+1)+' name=\''+pref[j].name+'\' required=\''+pref[j].required+'\'', 'text');
  	}
  	info.last_idx = info_dlg.area.get_children().length;
  	info.on_click();
  }

	pref = wid.preferences;
	if (pref.length) {
  	info = collapsable_list(info_dlg, 'Preferences');
  	for (j=0; j<pref.length; j++) {
  		var val = pref[j].value;
  		if (val=='') val = gpac.getOption(wid.section, pref[j].name);
  		gw_new_text(info_dlg.area, 'Preference #'+(j+1)+' name=\''+pref[j].name+'\' value=\''+val+'\' readOnly=\''+pref[j].readonly +'\'', 'text');
  	}
  	info.last_idx = info_dlg.area.get_children().length;
  	info.on_click();
  }

	info = collapsable_list(info_dlg, 'MPEG-U Migration Context');
	txt=wid.get_context();
	if (!txt) txt='';

	while (1) {
		var idx = txt.indexOf('\n', 0);
		if (idx>0) {
			gw_new_text(info_dlg.area, txt.substring(0, idx), 'text');
			txt = txt.substring(idx+1, txt.length);
		} else {
			gw_new_text(info_dlg.area, txt, 'text');
			break;
		}
	}
	info.last_idx = info_dlg.area.get_children().length;
	info.on_click();

  if (wid.num_interfaces) {
  	info = collapsable_list(info_dlg, 'MPEG-U Interfaces', 'button');
 		var spacer = gw_new_text(info_dlg.area, '', 'text');
  	spacer.hide();
  	info.first_idx = info_dlg.area.get_children().length;
    for (j=0; j<wid.num_interfaces; j++) {
  		var idx;
  		var ifce = wid.get_interface(j);
    	var item = collapsable_list(info_dlg, 'Interface #' + (j+1) + ' type: '+ifce.type);
      item.sublist = true;
  		gw_new_text(info_dlg.area, 'Multiple Binding: '+ifce.multipleBinding + ' - Service provider: '+ ifce.serviceProvider + ' - bound: ' + wid.is_interface_bound(ifce) , 'text');
  		for (k=0; k<ifce.num_messages; k++) {
  			var string, l;
  			var msg = ifce.get_message(k);
  			string = '  Message #'+ (k+1) + ':   ' + msg.name + '(';
  			for (l=0; l<msg.num_params; l++) {
  				par = msg.get_param(l);
  				string += (par.is_input ? 'in' : 'out') + ':' +par.name + ' ';
  			}
  			string += ')';
  			gw_new_text(info_dlg.area, string, 'text');
  		}
  	  item.last_idx = info_dlg.area.get_children().length;
    	item.on_click();
    	item.hide();
  	}
  	info.last_idx = info_dlg.area.get_children().length;
  	info.on_click();
  }

  info_dlg.area.spread_h = true;
  info_dlg.area.break_at_hidden = true;
  
  info_dlg.on_size = function(width, height) {
   var i;
   var children = this.area.get_children();
   for (i=0; i<children.length; i++) {
    if ((typeof children[i].first_idx != 'undefined') && (typeof children[i].sublist== 'undefined')) {
      children[i].set_size( (width>200) ? 200 : width, 20);
    } else {
      children[i].set_size(width, 16);
    }
   }
  }
  
  info_dlg.on_event = function(evt) {
   if (this.area && this.area.on_event(evt)) return true;
   return false;
  }

  info_dlg.set_size(320, 240);
  gpacui_show_window(info_dlg);
}


//widget close function
function widget_close(widget, force_remove)
{
	var is_comp = widget.is_component;

	if (widget.visible) {
		widget.visible = false;
		WidgetManager.corein_message(widget, 'hide');
		WidgetManager.corein_message(widget, 'deactivate');
		widget.deactivate();
		/*force disconnect of main resource - we do this because we are not sure when the widget_control will be destroyed due to JS GC*/
		if (widget.widget_control) {
			widget.widget_control.set_url('');
			widget.widget_control.close();
		}
	}
	if (!is_comp && (!widget.permanent || force_remove)) {
		WidgetManager.unload(widget, force_remove ? true : false);
	}
}

//widget remove function (close and unregister)
function widget_remove(wid) {
	if (typeof(wid.icon_dock) != 'undefined') {
		wid.icon_dock.close();
    wid.icon_dock = null;
	}		
	widget_close(wid, 1);
}

function new_migrate_callback(widget) {
 return function(renderer) {
  WidgetManager.migrate_widget(renderer, widget);
	widget_close(widget, 0);
 }
}

function on_widget_load() 
{
	WidgetManager.corein_message(this, 'activate');
	WidgetManager.corein_message(this, 'show');
	WidgetManager.corein_message(this, 'setSize', 'width', this.width, 'height', this.height, 'dpi', screen_dpi);
}


mpegu_targets = null;

function select_mpegu_target(callback)
{ 
  if (mpegu_targets) return;
  mpegu_targets = gw_new_file_open();
  mpegu_targets.set_label('Select Remote Display');
  mpegu_targets.callback = callback;

  mpegu_targets.on_close = function() {
   mpegu_targets = null;
  }
  /*override browse function*/
  mpegu_targets._on_mpegu_click = function() {
   	var target = (this.render_idx<0) ? null : WidgetManager.get_mpegu_service_providers(this.render_idx);

		mpegu_targets.callback(target);
		mpegu_targets.callback = null;
    mpegu_targets.close();
    mpegu_targets = null;
  }
  mpegu_targets._browse = function(dir, up) {
   var w, h, i, y;
   this.area.reset_children();
 
   for (i=0; ; i++) {
		var target = WidgetManager.get_mpegu_service_providers(i);
		if (!target) break;
		var	icon = 'icons/applications-internet.svg';
    var item = gw_new_icon_button(this.area, icon, target.Name, 'button');
    item.set_size(item.width, item.height);
    item.render_idx = i;
    item.on_click = this._on_mpegu_click;
   }  
   this.layout(this.width, this.height);
 }
 mpegu_targets.browse('');  
 mpegu_targets.go_up.hide();
 mpegu_targets.set_size(display_width, display_height);
 gpacui_show_window(mpegu_targets);
}


function new_widget_control(widget)
{
  var ctrl;
  

  var inline = gw_new_subscene(null);
  ctrl = gw_new_window_full(widget_display, true, null, 'offscreen', inline);
	ctrl.set_size(widget.width, widget.height);

  ctrl.inline = inline;
  ctrl.tools.spread_h = true;
  
	ctrl.component_bound = false;
	ctrl.widget = widget;
	widget.widget_control = ctrl;  
	widget.visible = true;
  
  ctrl.on_close = function() {
  	this.inline.url[0] = '';
  	this.widget.widget_control = null;  
		if (this.widget.discardable) widget_remove(this.widget);
		else widget_close(this.widget, 0);
		this.widget = null;
  }

  ctrl.tools.hide();
  gw_object_set_dragable(ctrl);

  gw_object_set_hitable(ctrl);
  ctrl.controls_visible = false;

	this.maximized = false;
  ctrl.on_double_click = function() {
   if (this.maximized) {
		this.maximized = false;
		this.move(this.widget.x, this.widget.y);
		this.set_size(this.prev_width, this.prev_height);
   } else {
		this.maximized = true;
		this.prev_width = this.widget.width;
		this.prev_height = this.widget.height;
		this.move(0, 0);
		this.set_size(display_width, display_height);
   }   
   this.controls_visible = false;
   this.tools.hide();
  }

  ctrl.on_click = function() {
    this.controls_visible = ! this.controls_visible;
    if (this.controls_visible) this.tools.show();
    else this.tools.hide();
  }
  /*push on top*/
  ctrl.on_down = function(value) {
		if (value) return;
		if (this.widget==null) return;

		//widget is a component, do not push on top but hide some controls
		if (this.widget.is_component) {
			if (this.component_bound) {
			  var chldren = this.tools.get_children();
				children[0].hide(); //close
				children[1].hide(); //remove
				children[4].hide(); //resize
			}
			return;
		}
		//otherwise push widget on top
		widget_display.push_to_top(this);
		//and push components
		comps = this.widget.components;
		for (i=0; i<comps.length; i++) {
			if (comps[i].widget_control && comps[i].widget_control.component_bound) {
				widget_display.push_to_top(comps[i].widget_control);
			}
		}
  }

  ctrl._orig_move = ctrl.move;
  ctrl.move = function(x, y) {
    this.widget.x = x;
		this.widget.y = y;
		this._orig_move(x, y);
	}

  ctrl.on_drag = function(x, y) {
		if (this.maximized) return;
    this.move(x, y);
  }
  ctrl.on_event = function(evt) {
   var x, y;
   if (evt.type != GF_EVENT_KEYDOWN) return false;
   if (!this.controls_visible) return false;

   x = this.widget.x;
   y = this.widget.y;
   if (evt.keycode=='Up') y += 10;
   else if (evt.keycode=='Down') y -= 10;
   else if (evt.keycode=='Left') x -= 10;
   else if (evt.keycode=='Right') x += 10;
   else return false;
   this.move(x, y);
   return true;
  }
 
  /*widget is not temporary*/
	if (!widget.discardable && widget.icon_dock) {
    var icon = ctrl.add_tool(gwskin.images.trash, gwskin.labels.trash);
    icon.on_click = function() { widget_remove(this.dlg.widget); };  
  }
  
  if (UPnP_Enabled) {
    ctrl.remote = ctrl.add_tool(gwskin.images.remote_display, gwskin.labels.remote_display);
    ctrl.remote.on_click = function() { 
      var dlg = select_mpegu_target(new_migrate_callback(this.dlg.widget) );    
    };  
  	
    ctrl.show_remote = function(show) {
     if (show) this.remote.show();
     else this.remote.hide();
    }
  }  

  var icon = ctrl.add_tool(gwskin.images.information, gwskin.labels.information);
  icon.on_click = function() { 
    display_widget_info(this.dlg.widget); 
  };  

  var icon = ctrl.add_tool(gwskin.images.resize, gwskin.labels.resize);
  gw_object_set_dragable(icon);
	ctrl.prev_x=0;
	ctrl.prev_y=0;
  icon.begin_drag = function() {
  	this.dlg.prev_x=this.startx;
	  this.dlg.prev_y=this.starty;
  }
  icon.on_drag = function(valx, valy) {
    var _dlg = this.dlg;
		if (_dlg.widget.width + 2*(valx - _dlg.prev_x) < widget_min_size) return;
		if (_dlg.widget.height + 2*(valy-_dlg.prev_y) < widget_min_size) return;

		_dlg.widget.width += 2*(valx - _dlg.prev_x);
		_dlg.prev_x = valx;
		_dlg.widget.height += 2*(valy - _dlg.prev_y);
		_dlg.prev_y = valy;
		_dlg.set_size(_dlg.widget.width, _dlg.widget.height);
  }
  
  ctrl.set_url = function(url) {
 	 ctrl.inline.url[0] = url;
  }
  ctrl.predestroy = function() {
   this.inline = null;
   this.remote = null;
   this.widget = null;
  }
		
	ctrl.sub_w = 0;
	ctrl.sub_h = 0;
	ctrl.sub_x = 0;
	ctrl.sub_y = 0;
	ctrl.sub_vp_w = 0;
	ctrl.sub_vp_h = 0;

  ctrl.on_widget_vp_changed = function(evt) {
		this.sub_vp_w = evt.width;
		this.sub_vp_h = evt.height;
		this.sub_vp_x = evt.offset_x;
		this.sub_vp_y = evt.offset_y;
		this.sub_w = evt.vp_width;
		this.sub_h = evt.vp_height;
  }
	ctrl.inline.addEventListener('gpac_vp_changed', ctrl.on_widget_vp_changed, 0);
		
  ctrl.set_tool_size(widget_tool_size);  
	ctrl.set_size(widget.width, widget.height);
	if (widget.x < -display_width/2) widget.x = 0;
	else if (widget.x > display_width/2) widget.x = 0;
	if (widget.y < -display_height/2) widget.y = 0;
	else if (widget.y > display_height/2) widget.y = 0;
	ctrl.move(widget.x, widget.y);

	/*this will setup the scene graph for the widget in order to filter input and output communication pins*/
	widget.activate(ctrl.inline);

	ctrl.set_url(widget.main);

	/*send notifications once the widget scene is loaded*/
	widget.on_load = on_widget_load;

  ctrl.show();
  return ctrl;
}

function flash_window(wnd) {
	wnd.time = gw_new_timer(true);
	wnd.time.set_timeout(0.25, true);
	wnd.time.ctrl = wnd;
	wnd.time.on_fraction = function(val) {
		var scale = (val<0.5) ? 1+val/2 : 1.5-val/2;
		this.ctrl.scale.x = this.ctrl.scale.y = scale;
	}
	wnd.time.on_active = function (val) {
		 if (!val) {
      this.ctrl.time = null;
      this.ctrl = null;
     }
  }
	wnd.time.stop(1);
	wnd.time.start(0);
}

//widget launcher function
function widget_launch(wid) {
	var widg_ctrl;

	//assign default size to the widget
	if (wid.width == undefined) {
		wid.width = wid.defaultWidth;
		if (wid.width == 0) wid.width = widget_default_size;
	}
	if (wid.height == undefined) {
		wid.height = wid.defaultHeight;
		if (wid.height == 0) wid.height = widget_default_size;
	}
	if (wid.x== undefined) wid.x = 0;
	if (wid.y== undefined) wid.y = 0;

	widg_ctrl = new_widget_control(wid);
}


//starts a widget
function on_widget_launch() {
	if (this.widget.visible) {
		var awid;
		if (!this.widget.multipleInstances) return;
		awid = WidgetManager.open(this.widget.manifest, null);
		widget_launch(awid);
	} else {
		widget_launch(this.widget);
	}
  show_dock(false);
}


function widget_get_icon(widget)
{
	var icon = 'icons/image-missing.svg';
	var preferredIconType = '.svg';

	for (var i = 0; i < widget.icons.length; i++) {
		icon = widget.icons[i].relocated_src;
		if (widget.icons[i].relocated_src.indexOf(preferredIconType) > 0) {
			break;
		}
	}
	return icon;
}

function widget_insert(widget)
{
	/*insert the widget icon*/
	if (widget.permanent && !widget.is_component)
		widget_insert_icon(widget);

	/*and load the widget - comment this line to disable auto load of widget*/
	widget_launch(widget);
}

function __get_int(arg)
{
		return (typeof arg == 'string') ? parseInt(arg) : arg;
}

function widget_request_size(widget, args)
{
	if (args.length==2) {
		w = __get_int(args[0]);
		h = __get_int(args[1]);
		widget.widget_control.set_size(w, h);
	}
}

function widget_request_show(widget, args)
{
	widget.widget_control.show();
}
function widget_request_hide(widget, args)
{
	widget.widget_control.hide();
}
function widget_request_activate(widget, args)
{
	if (!widget.visible)
		widget_launch(widget);
}
function widget_request_deactivate(widget, args)
{
	if (widget.visible)
		widget_close(widget, 0);
}

function widget_request_attention(widget, args)
{
	if (widget.visible) {
		widget_display.push_to_top(widget.widget_control);
		flash_window(widget.widget_control);
	}
}

function widget_request_notification(widget, args)
{
  var notif = gw_new_message(null, ''+widget.name+' Alert!', args[0]);
//	widget_display.push_to_top(notif);
  gpacui_show_window(notif);
	notif.set_size(240, 120);
}

function widget_refresh_components_layout(ctrl, send_resize, comp_target)
{
	var i;
	var x, y, w, h, scale_x, scale_y;
	var comps;

	/*local to subscene transformation not known*/
	if (!ctrl.sub_w) return;
	if (!ctrl.sub_h) return;

	comps = ctrl.widget.components;
	for (i=0; i<comps.length; i++) {
		var comp = comps[i];
		if (!comp.widget_control || !comp.widget_control.component_bound) continue;

		//compute scale from Widget Manager coord system to widget internal coordinate system
		scale_x = ctrl.sub_vp_w / ctrl.sub_w;
		scale_y = ctrl.sub_vp_h / ctrl.sub_h;

		w = comp.widget_control.place_w * scale_x;
		h = comp.widget_control.place_h * scale_y;

		x = ctrl.translation.x - ctrl.widget.width/2 + ctrl.sub_vp_x + comp.widget_control.place_x * scale_x + w/2;
		comp.widget_control.translation.x = x;

		y = ctrl.widget.height/2 + ctrl.translation.y - h/2 - ctrl.sub_vp_y - comp.widget_control.place_y * scale_y;
		comp.widget_control.translation.y = y;

		if (send_resize || (comp_target==comp))
			comp.widget_control.set_size(w, h);
	}
}

function widget_place_component(widget, args)
{
	var comp = widget.get_component(args[0]);

	if (comp==null) {
		log(l_err, 'Component '+args[0]+' cannot be found in widget '+widget.name);
		return;
	}
	comp.widget_control.place_x = __get_int(args[1]);
	comp.widget_control.place_y = __get_int(args[2]);
	comp.widget_control.place_w = __get_int(args[3]);
	comp.widget_control.place_h = __get_int(args[4]);
	comp.widget_control.place_z = __get_int(args[5]);
	comp.widget_control.component_bound = true;
	widget_refresh_components_layout(widget.widget_control, false, comp);
}



//
// implementation of core:out install widget
//
function widget_request_install(wid, args)
{
	var wid_url = args[0];
	/*locate widget with same URL*/
	var j, count = WidgetManager.num_widgets;
	for (j = 0; j < count; j++) {
		var wid = WidgetManager.get(j);
		if (wid.url == wid_url) {
			if (!wid.in_panel) {
				widget_insert_icon(wid);
			}
			break;
		}
	}
	alert('opening widget '+wid_url);
	/*not found, install new widget*/
	if (j == count) {
		var new_wid = WidgetManager.open(wid_url, null, wid);
		if (new_wid==null) return;
		widget_insert_icon(new_wid);
	}

	var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
	if (ifce != null) {
		wmjs_core_out_invoke_reply(coreOut.installWidgetMessage, ifce.get_message("installWidget"), wid, 1); // send return code 1 = success
	}
}
function widget_migrate_component(wid, args)
{
	var comp = wid.get_component(args[0], true);
	var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");

	if (comp==null) {
		log(l_err, 'Component '+args[0]+' cannot be found in widget '+wid.name);
		if (ifce != null) {
			wmjs_core_out_invoke_reply(coreOut.migrateComponentMessage, ifce.get_message("migrateComponent"), wid, 0);
		}
		return;
	}
	comp.widget_control = null;
	if (args.length > 1 && args[1] != null) {
		alert('Migrating component to ' + UPnP.GetMediaRenderer(parseInt(args[1])).Name);
		WidgetManager.migrate_widget(UPnP.GetMediaRenderer(parseInt(args[1])), comp);
		widget_close(comp);
	} else {
    var dlg = select_mpegu_target(new_migrate_callback(comp) );    
	}
	if (ifce != null) {
		wmjs_core_out_invoke_reply(coreOut.migrateComponentMessage, ifce.get_message("migrateComponent"), wid, 1); // send return code 1 = success
	}
}

function widget_migration_targets(wid, args)
{
	var count = UPnP.MediaRenderersCount, codes = new Array(), names = new Array(), descriptions = new Array(), i, i;

	for (i = 0; i < count; i++) {
		var render = UPnP.GetMediaRenderer(i);
		codes.push(""+i);
		names.push(render.Name);
		descriptions.push(render.HostName +" "+ render.UUID);
	}
	i = null;
	var ifce_count = wid.num_interfaces, j;
	for (j = 0; j < ifce_count; j++) {
		var ifce = wid.get_interface(j);
		if (ifce.type == "urn:mpeg:mpegu:schema:widgets:core:out:2010") {
			i = ifce;
			break;
		}
	}
	if (i != null) {
		wmjs_core_out_invoke_reply(coreOut.requestMigrationTargetsMessage, i.get_message("requestMigrationTargets"),
			wid, codes, names, descriptions);
	}
}


//
// implementation of core:out activate temporary widget
//
function widget_activate_temporary_widget(wid, args) {
	var w = WidgetManager.open(args[0], null);
	if (w != null) widget_launch(w);
	var ifce = getInterfaceByType(wid, "urn:mpeg:mpegu:schema:widgets:core:out:2010");
	if (ifce != null) {
		wmjs_core_out_invoke_reply(coreOut.activateTemporaryWidgetMessage, ifce.get_message("activateTemporaryWidget"),
			wid, (w != null ? 1 : 0)); // send return code 1 = success
	}
}

function setup_extension(extension)
{ 
  var count, i;

  /*WidgetManager module not present*/ 
  if (typeof(WidgetManager) == 'undefined') return 0;
  
  /*load MPEG-U*/ 
  Browser.loadScript('mpegu-core.js', true); 
  widget_manager_init();
   
  extension.icon = 'applications-system.svg';
  extension.label = 'Widget Manager';
  extension.desc = 'Configure Widgets';
  extension.launch = open_widget_manager;
  
  extension.initialize = function(extension) {
		WidgetManager.on_widget_remove = widget_remove;
		WidgetManager.on_widget_add = widget_insert;
		WidgetManager.coreOutSetSize = widget_request_size;
		WidgetManager.coreOutShow = widget_request_show;
		WidgetManager.coreOutHide = widget_request_hide;
		WidgetManager.coreOutRequestActivate = widget_request_activate;
		WidgetManager.coreOutRequestDeactivate = widget_request_deactivate;
		WidgetManager.coreOutShowNotification = widget_request_notification;
		WidgetManager.coreOutPlaceComponent = widget_place_component;
		WidgetManager.coreOutGetAttention = widget_request_attention;
		WidgetManager.coreOutInstallWidget = widget_request_install;
		WidgetManager.coreOutMigrateComponent = widget_migrate_component;
		WidgetManager.coreOutRequestMigrationTargets = widget_migration_targets;
		WidgetManager.coreOutActivateTemporaryWidget = widget_activate_temporary_widget;


   	gpacui_show_window(widget_display);
   	
  	/*restore our widgets*/
  	count = WidgetManager.num_widgets;
  	for (i=0; i<count; i++) {
  		var wid = WidgetManager.get(i);
  		if (wid == null) continue;
  		wid.device = null;
  		wid.device_ip = null;

  		if (wid.in_panel == true) {
        var icon = gpacui_insert_dock_icon(wid.name, widget_get_icon(wid));
  			icon.widget = wid;
  			icon.on_click = on_widget_launch;
  			wid.icon_dock = icon;
  		}

  		if (wid.visible) {
  			widget_launch(wid);
  		}
  	}
  	check_widget_display(display_width, display_height);
  }	

  if (UPnP_Enabled) {  
    extension.on_upnp_add = function(name, uuid, is_add) {
    	var i, count;
    	var show = UPnP.MediaRenderersCount ? 1 : 0;
    	count = WidgetManager.num_widgets;
    	for (i=0; i<count; i++) {
    		wid = WidgetManager.get(i);
    		if (wid == null) continue;
    		if (!wid.widget_control) continue;
    		wid.widget_control.show_remote(show);
    	}
    }
    extension.on_media_open = function(url, src_ip) {
    	if (! WidgetManager.probe(url)) return 0;
   		var new_wid = WidgetManager.open(url, src_ip);
  		if (new_wid!=null) {
  	     widget_insert(new_wid);
  		}
  		return 1;
    }
  }
  extension.on_resize = check_widget_display;
  
  /*setup all widgets*/
  return 1;
}

