/**
	 * Get the associated model for this instance, if available.
	 *
	 * @return Widget_2_1|null
	 */
	public function getWidget(){
		if($this->_widget === null){
			$pagedat = $this->splitParts();

			// This will be a Widget object.
			/** @var Widget_2_1 $c */
			$this->_widget = Widget_2_1::Factory($pagedat['controller']);

			// Make sure it's linked
			$this->_widget->_instance = $this;

			// Was installable passed in?  It may contain data useful to the widget.
			if($this->get('installable')){
				$this->_widget->_installable = $this->get('installable');
			}

			// Pass in any base and customer parameters
			$this->_widget->_params = $pagedat['parameters'];
		}

		return $this->_widget;
	}
	/**
	 * Display a listing of all widgets registered in the system.
	 */
	public function admin(){
		$view = $this->getView();
		$request = $this->getPageRequest();

		$viewer = \Core\user()->checkAccess('p:/core/widgets/manage');
		$manager = \Core\user()->checkAccess('p:/core/widgets/manage');
		if(!($viewer || $manager)){
			return View::ERROR_ACCESSDENIED;
		}

		// Build a list of create pages for all registered components.
		$components    = Core::GetComponents();
		$pages         = [];
		$skins         = [];
		$selected      = null;
		$selectedtype  = null;
		$baseurl       = null;
		$selectoptions = [];
		$links         = [];
		$theme         = ThemeHandler::GetTheme();
		$formtheme     = null;
		$formskin      = null;
		$formtemplate  = null;

		foreach($components as $c){
			/** @var Component_2_1 $c */

			$viewdir = $c->getViewSearchDir();
			if($viewdir){
				$dirlen = strlen($viewdir);
				$component = $c->getName();

				$dh = \Core\Filestore\Factory::Directory($viewdir);
				//$pagetplfiles = $dh->ls('tpl', true);
				$pagetplfiles = $dh->ls(null, true);

				// not sure why getFilename(path) isn't working as expected, but this works too.
				foreach($pagetplfiles as $obj){

					// I don't want directories.
					if($obj instanceof \Core\Filestore\Directory) continue;

					/** @var $obj \Core\Filestore\File */
					$file = substr($obj->getFilename(), $dirlen);

					// Since this is a template, it may actually be in a different location than where the package maintainer put it.
					// ie: user template user/templates/pages/user/view.tpl may be installed to themes/myawesometheme/pages/user/view.tpl instead.
					$tpl = Core\Templates\Template::Factory($file);

					if($tpl->hasWidgetAreas()){
						$pagetitle = $file;
						if(strpos($pagetitle, 'pages/') === 0){
							$pagetitle = substr($pagetitle, 6);
						}
						// Replace directory slashes with a space
						$pagetitle = str_replace(['/', '-'], ' ', $pagetitle);
						// Capitalize them
						$pagetitle = ucwords($pagetitle);
						// And trim off the ".tpl" suffix.
						$pagetitle = substr($pagetitle, 0, -4);
						$pages[$file] = $pagetitle;
					}
				}
			}

			foreach($c->getXML()->getElements('/widgets/widgetcreate') as $node){
				/** @var DOMElement $node */

				if($node->getAttribute('baseurl')){
					$nodebaseurl = $node->getAttribute('baseurl');
					$image = '';
				}
				elseif($node->getAttribute('class')){
					/** @var Widget_2_1 $obj */
					$obj = Widget_2_1::Factory($node->getAttribute('class'));
					$nodebaseurl = '/widget/create?class=' . $node->getAttribute('class');
					if($obj){
						$image = $obj->getPreviewImage();
					}
					else{
						\Core\set_message('Invalid "widgetcreate" found in ' .$node->getAttribute('class') . ', ' . $node->getAttribute('title'), 'error');
						$image = '';
					}
				}
				else{
					\Core\set_message('Invalid "widgetcreate" found in ' . $c->getName() . ', ' . $node->getAttribute('title'), 'error');
					continue;
				}

				$links[] = [
					'baseurl' => $nodebaseurl,
					'title' => $node->getAttribute('title'),
				    'preview' => $image,
				];
			}
		}

		// Build the array of skins for the current theme
		$themeskins  = $theme->getSkins();
		$defaultskin = null;
		foreach($themeskins as $dat){

			$skins[ 'skins/' . $dat['file'] ] = $dat['title'];

			if($dat['default']){
				$defaultskin = 'skins/' . $dat['file'];
			}
		}

		// Now that the various templates have been loaded into a flat array, I need to sort them.
		asort($pages);
		asort($skins);

		foreach($skins as $k => $v){
			$selectoptions[ $k ] = 'Skin: ' . $v;
		}
		foreach($pages as $k => $v){
			$selectoptions[ $k ] = 'Page: ' . $v;
		}

		if($request->getParameter('baseurl')){
			// It's a URL-specific request, lookup which template that page used last.
			$baseurl  = $request->getParameter('baseurl');
			$page     = PageModel::Construct($baseurl);

			if(!isset($pages[ $page->get('last_template') ])){
				\Core\set_message('Requested page template does not seem to contain any widget areas.', 'error');
				\Core\go_back();
			}

			$selected = $page->get('last_template');
			$selectedtype = 'url';
			$formtemplate = $selected;
		}
		elseif($request->getParameter('template')){
			$selected = $request->getParameter('template');

			if(isset($pages[ $selected ])){
				$selectedtype = 'page';
				$formtemplate = $selected;
			}
			else{
				$selectedtype = 'skin';
				$formtheme = $theme->getKeyName();
				$formskin  = $selected;
			}
		}
		else{
			// Just use the default theme skin.
			$selected = $defaultskin;
			$selectedtype = 'skin';$formtheme = $theme->getKeyName();
			$formskin  = $selected;
		}

		$template     = \Core\Templates\Template::Factory($selected);
		$areas        = $template->getWidgetAreas();
		$installables = [0 => ''];

		foreach($areas as $k => $dat){
			// Ensure that each area has a widgets array, (even if it's empty)
			$areas[$k]['widgets'] = [];
			$installables[] = $dat['installable'];
		}
		$installables = array_unique($installables);

		$factory = new ModelFactory('WidgetInstanceModel');
		$factory->order('weight');
		if(Core::IsComponentAvailable('multisite') && MultiSiteHelper::IsEnabled()){
			$factory->whereGroup('or', ['site = -1', 'site = ' . MultiSiteHelper::GetCurrentSiteID()]);
		}

		if($selectedtype == 'skin'){
			// First, the skin-level where clause.
			$skinwhere = new Core\Datamodel\DatasetWhereClause();
			$skinwhere->setSeparator('AND');
			//$skinwhere->addWhere('theme = ' . $theme->getKeyName());
			$skinwhere->addWhere('template = ' . $selected);
			$factory->where($skinwhere);
		}
		elseif($selectedtype == 'page'){
			$factory->where('template = ' . $selected);
		}
		elseif($selectedtype == 'url'){
			$factory->where('page_baseurl = ' . $baseurl);
		}
		else{
			\Core\set_message('Invalid/unknown template type', 'error');
			\Core\go_back();
		}


		foreach($factory->get() as $wi){
			/** @var $wi WidgetInstanceModel */

			$a = $wi->get('widgetarea');
			$areas[$a]['widgets'][] = $wi;
		}

		$available = WidgetModel::Find(['installable IN ' . implode(', ', $installables)]);

		/*
		$table = new Core\ListingTable\Table();
		$table->setName('/admin/widgets');
		$table->setModelName('WidgetModel');
		// Add in all the columns for this listing table.
		$table->addColumn('Title', 'title');
		if(Core::IsComponentAvailable('enterprise') && MultiSiteHelper::IsEnabled() && \Core\user()->checkAccess('g:admin')){
			$table->addColumn('Site', 'site', false);
			$ms = true;
		}
		else{
			$ms = false;
		}
		$table->getModelFactory()->where('installable IN ' . implode(', ', $installables));
		$table->addColumn('Base URL', 'baseurl');
		$table->addColumn('Installable', 'installable');
		$table->addColumn('Created', 'created');

		$table->loadFiltersFromRequest();
		*/

		$view->mastertemplate = 'admin';
		$view->title = 'All Widgets';
		//$view->assign('table', $table);
		$view->assign('available_widgets', $available);
		$view->assign('links', $links);
		$view->assign('manager', $manager);
		$view->assign('theme', $formtheme);
		$view->assign('skin', $formskin);
		$view->assign('template', $selected);
		$view->assign('page_template', $formtemplate);
		$view->assign('page_baseurl', $baseurl);
		$view->assign('options', $selectoptions);
		$view->assign('selected', $selected);
		$view->assign('areas', $areas);
		//$view->assign('multisite', $ms);
	}