<?PHP

  require_once ('twIf/generic/multi/classed.php');
  require_once ('twIf/generic/controllable/listing.php');
  require_once ('twIf/generic/controllable/editor.php');
  
  class twIf_Generic_Multi_Classed_Selector extends twIf_Generic_Multi_Classed {
    const SELECTOR_URL = 'select';
    const SELECTOR_CAPTION = 'Select an item';
    const SELECTOR_INTRODUCTION = 'Please select one of the following items for editing';
    
    // Prohibit item-selection when opening creator
    const CREATOR_WITHOUT_ITEM = false;
    
    const ALLOW_CREATE = false;
    const ALLOW_EDIT = false;
    const ALLOW_DELETE = false;
    
    private $Selector = null;
    private $onSelector = false;
    private $Options = array ();
    
    // {{{ __construct
    /**
     * Create a new Interface to handle subclasses with an object assigned
     * 
     * @param array $URL
     * @param string $Base
     * 
     * @access friendly
     * @return void
     */
    function __construct ($URL, $Base, $urlMode = self::MODE_URL) {
      // Set the base because we want to forward it
      $this->setBase ($Base);
      
      // Insert Listing-Class
      $this->assignURLClass ($this->getSelectorURL (), $this->getSelectorClass (), $this->getSelectorCaption (), true);
      
      // Install default URL-Handler if there is none
      if (!$this->haveDefaultURL ())
        $this->assignDefaultURL ($this->getSelectorURL ());
      
      parent::__construct ($URL, $this->getBase (), $urlMode);
    }
    // }}}
    
    // {{{ assignURLClass
    /**
     * Assign an URL to a given class
     * 
     * @param string $URL URL of subclass
     * @param string $Class Which class to use
     * @param string $onNavigation (optional) Link this class with this caption on navigation
     * @param bool $First (optional) Put the class in first place on navigation
     * @param array $URL (optional) Just assign the class if there is an item in this URL
     * @param string $Base (optional) Use this base
     * @param string $selectorName (optional) Include this class in options on the selector
     * 
     * @access protected
     * @return bool
     **/
    protected function assignURLClass ($URL, $Class, $onNavigation = null, $First = false, &$cURL = false, &$Base = null, $selectorName = null) {
      if ($selectorName !== null) {
        // Check wheter to set a base
        if ((strlen ($this->getBase ()) < 2) && ($Base !== null))
          $this->setBase ($Base);
        
        $this->probeItem ($cURL, $Base);
        $this->Options [$selectorName] = $this->generateSubclassLink ($URL, true, '%{md5::getID()}');
        
        $Base = $this->getBase ();
      }
       
      return parent::assignURLClass ($URL, $Class, $onNavigation, $First, $cURL, $Base);
    }
    // }}}
    
    // {{{ loadSubclass  
    /**
     * Load a given subclass
     * 
     * @param string $Class Name of subclass
     * @param array $URL
     * @param string $Base
     * @param bool $Strip (optional, default) Strip first chunk of URL and take it as base
     * 
     * @access private
     * @return object
     */
    protected function loadSubclass ($Class, $URL, $Base, $Strip = true) {
      // Strip any item if not wanted in creator
      if (($URL [0] == $this->getSelectorURL ()) && is_object ($this->getItem ()) && self::findConstant ('CREATOR_WITHOUT_ITEM', false))
        $Base = dirname ($Base);
      
      // Inherit to our parent first
      $rc = parent::loadSubclass ($Class, $URL, $Base, $Strip);

      return $rc;
    }
    // }}}
    
    // {{{ getSelectorClass
    /**
     * Retrive the name of the class to use for the selector-widget
     * 
     * @access private
     * @return string
     **/
    private function getSelectorClass () {
      if ($this->getAllowEdit () || $this->getAllowCreate ())
        return 'twIf_Generic_Controllable_Editor';
      
      return 'twIf_Generic_Controllable_Listing';
    }
    // }}}
    
    // {{{ getSelectorURL
    /**
     * Determine on which URL to place the selector
     * 
     * @access protected
     * @return string
     **/
    protected function getSelectorURL () {
      return self::findConstant ('SELECTOR_URL', self::SELECTOR_URL);
    }
    // }}}
    
    // {{{ getSelectorCaption
    /**
     * Retrive the subcaption for the listing-widget
     * 
     * @access protected
     * @return string
     **/
    protected function getSelectorCaption () {
      return self::findConstant ('SELECTOR_CAPTION', self::SELECTOR_CAPTION);
    }
    // }}}
    
    // {{{ getSelectorIntroduction
    /**
     * Retrive the introduction for the listing-widget
     * 
     * @access protected
     * @return string
     **/
    protected function getSelectorIntroduction () {
      return self::findConstant ('SELECTOR_INTRODUCTION', self::SELECTOR_INTRODUCTION);
    }
    // }}}
    
    // {{{ getEnablePaging
    /**
     * Check wheter to enable paging on the listing-widget
     * 
     * @access protected
     * @return bool
     **/
    protected function getEnablePaging () {
      return null;
    }
    // }}}
    
    // {{{ getListParams
    /**
     * Retrive the listing-parameters for the listing-widget
     * 
     * @access protected
     * @return array
     **/
    protected function getListParams () {
      return null;
    }
    // }}}
    
    // {{{ getSortParams
    /**
     * Retrive the sorting-parameters for the listing-widget
     * 
     * @access protected
     * @return array
     **/
    protected function getSortParams () {
      return null;
    }
    // }}}
    
    // {{{ getFields
    /**
     * Retrive field-definition for the listing-widget
     * 
     * @access protected
     * @return array
     **/
    protected function getFields () {
      return null;
    }
    // }}}
    
    // {{{ getOptions
    /**
     * Retrive the options for the listing-widget
     * 
     * @access protected
     * @return array
     **/
    protected function getOptions () {
      // Check if we have a selector-widget assigned
      if (!is_object ($this->Selector))
        return null;
      
      // Check if we are the default widget
      if (($URL = $this->getDefaultURL ()) == $this->getSelectorURL ())
        $URL = '';
      
      $Options = array ();
      
      if ($this->getAllowEdit ()) {
        $Options = $this->Selector->getOptions ();
        
        # if (is_object ($this->getItem ()))
        #   return $Options;
        
        $URL = $this->Selector->getEditorURL (false);
        
        foreach ($Options as $Caption=>$Link)
          if ($Link == $URL) {
            # $Options [$Caption] = $this->generateSubclassLink (substr ($URL, strlen ($this->getBase ())), true, '%{md5::getID()}');
            $Options [$Caption] = $this->generateSubclassLink ($this->getSelectorURL () . '/%{md5::getID()}', true, '%{md5::getID()}');
            break;
          }
      } elseif (count ($O = $this->Selector->getOptions ()) > 0)
        $Options = $O;
      
      // Insert selection-link
      elseif (count ($this->Options) == 0)
        $Options = array (
          'Select' => $this->generateSubclassLink ($URL, true, '%{md5::getID()}'),
        );
      
      $Options = array_merge ($Options, $this->Options);
      
      return $Options;
    }
    // }}}
    
    // {{{ getHighlight
    /**
     * Retrive filter-definition for highlighting
     * 
     * @access protected
     * @return array
     **/
    protected function getHighlight () {
      return null;
    }
    // }}}
    
    // {{{ getEnableToggle
    /**
     * Define wheter to add an enable-toogle to listing-widget
     * 
     * @access protected
     * @return bool
     **/
    protected function getEnableToggle () {
      return self::findConstant ('ENABLE_TOGGLE', false);
    }
    // }}}
    
    // {{{ getAllowDelete
    /**
     * Define wheter to add an delete-link to listing-widget
     * 
     * @access protected
     * @return bool
     **/
    protected function getAllowDelete () {
      return self::findConstant ('ALLOW_DELETE', false);
    }
    // }}}
    
    // {{{ getAllowCreate
    /**
     * Define wheter items may be created
     * 
     * @access protected
     * @return bool
     **/
    protected function getAllowCreate () {
      return self::findConstant ('ALLOW_CREATE', false);
    }
    // }}}
    
    // {{{ getAllowEdit
    /**
     * Define wheter items may be modified
     * 
     * @access protected
     * @return bool
     **/
    protected function getAllowEdit () {
      return self::findConstant ('ALLOW_EDIT', false);
    }
    // }}}
    
    // {{{ getEditorCaption
    /**
     * Retrive the caption for the editor-widget
     * 
     * @access protected
     * @return string
     **/
    protected function getEditorCaption () {
      return self::findConstant ('EDITOR_CAPTION', twIf_Generic_Editor::EDITOR_CAPTION);
    }
    // }}}
    
    // {{{ getCreatorCaption
    /**
     * Retrive the caption for the creator-widget
     * 
     * @access protected
     * @return string
     **/
    protected function getCreatorCaption () {
      return self::findConstant ('CREATOR_CAPTION', twIf_Generic_Editor::CREATOR_CAPTION);
    }
    // }}}
    
    // {{{ getEditorFields
    /**
     * Override fields for editor-definition
     * 
     * @access protected
     * @return array
     **/
    protected function getEditorFields () {
      return null;
    }
    // }}}
    
    // {{{ getCreatorFields
    /**
     * Override fields for creator-definition
     * 
     * @access protected
     * @return array
     **/
    protected function getCreatorFields () {
      return null;
    }
    // }}}
    
    // {{{ getCreatorParams
    /**
     * Retrive the parameters for the constructor of new elements
     * 
     * @access protected
     * @return array
     **/
    protected function getCreatorParams () {
      return null;
    }
    // }}}
    
    // {{{ getCreatorStrict
    /**
     * Define if we handle creator-parameters strictly
     * 
     * @access protected
     * @return bool
     **/
    protected function getCreatorStrict () {
      return null;
    }
    // }}}
    
    // {{{ prepare
    /**
     * Forward all parameters to our listing-widget
     * 
     * @access public
     * @return bool
     */
    public function prepare () {
      $rc = $this->Subclass;
      $isListing = ($rc instanceof twIf_Generic_Controllable_Listing);
      $isEditor = ($rc instanceof twIf_Generic_Controllable_Editor);
      
      // Forward our listing-settings
      if ($isListing || $isEditor) {
        $this->Selector = $rc;
        
        $rc->setClassname ($this->getClass ());
        $rc->setAllowDelete ($this->getAllowDelete ());
        
        if ($isEditor) {
          $rc->setAllowEdit ($this->getAllowEdit ());
          $rc->setAllowCreate ($this->getAllowCreate ());
          
          $rc->setEditorCaption ($this->getEditorCaption ());
          $rc->setEditorFields ($this->getEditorFields ());
          
          $rc->setCreateCaption ($this->getCreatorCaption ());
          $rc->setCreateFields ($this->getCreatorFields ());
          $rc->setCreateParams ($this->getCreatorParams ());
          $rc->setCreateStrict ($this->getCreatorStrict ());
          
          $rc->setCallbackCreate (array ($this, 'callbackCreate'));
          $rc->setCallbackUpdate (array ($this, 'callbackUpdate'));
        }
        
        $rc->setCaption ($this->getSelectorCaption ());
        $rc->setIntroduction ($this->getSelectorIntroduction ());
        
        $rc->setPaging ($this->getEnablePaging ());
        $rc->setListParams ($this->getListParams ());
        $rc->setSortParams ($this->getSortParams ());
        $rc->setFields ($this->getFields ());
        $rc->setOptions ($this->getOptions ());
        $rc->setHighlight ($this->getHighlight ());
        $rc->setEnableToggle ($this->getEnableToggle ());
      }
      
      return parent::prepare ();
    }
    // }}}
    
    // {{{ getNaviation
    /**
     * Retrive Navigation-definition for this interface
     * 
     * @access protected
     * @return array
     **/
    protected function getNavigation () {
      #if ((!is_object ($this->getItem ()) || !$this->getAllowEdit ()) &&
      #    (!is_object ($this->Selector) || !($this->Selector instanceof twIf_Generic_Editor) || (!$this->Selector->onCreator() && !$this->Selector->onEditor ())))
      #  return parent::getNavigation ();
      # We have an item and may edit
      # We have a selector of type editor and are on creator or editor
      
      if (!$this->getAllowCreate () && ((!is_object ($this->Selector) || !($this->Selector instanceof twIf_Generic_Editor) || !$this->getAllowEdit ())))
        return parent::getNavigation ();
      
      # We have an item and may edit
      # We have no item and may create
      
      if (is_object ($this->Selector) && ($this->Selector instanceof twIf_Generic_Editor)) {
        if ($this->Selector->onEditor ())
          $Item = array (
            'Caption' => $this->Selector->getEditorCaption (),
            'URL' => $this->Selector->getEditorURL (true),
            'Selected' => true,
          );
        elseif ($this->Selector->onCreator ())
          $Item = array (
            'Caption' => $this->Selector->getCreateCaption (),
            'URL' => $this->Selector->getCreatorURL (),
            'Selected' => true,
          );
      }
      
      if (!is_array ($Item)) {
        if (is_object ($this->getItem ()))
          $Item = array (
            'Caption' => $this->getEditorCaption (),
            'URL' => ($this->urlMode == self::MODE_URL ? $this->getBase () . $this->getSelectorURL () . '/' . md5 ($this->getItem ()->getID ()) : '#'), # TODO: Implement Parameter-Mode
          );
        else
          $Item = array (
            'Caption' => $this->getCreatorCaption (),
            'URL' => $this->getBase () . $this->getSelectorURL () . '/' . twIf_Generic_Editor::CREATE_LINK,
          );
      }
      
      $Base = parent::getNavigation (true);
      $out = array ();
      $idx = null;
      $sel = $Item ['Selected'];
      
      while (count ($Base) > 0) {
        $nItem = array_shift ($Base);
        
        if ($nItem ['Caption'] == $this->getSelectorCaption ()) {
          if ($Item ['Selected'] && $Item ['Selected'])
            $nItem ['Selected'] = false;
          
          $idx = count ($out);
          $out [] = $nItem;
          $out [] = $Item;
          
          continue;
        }
        
        if ($nItem ['Selected'])
          $sel = true;
        
        $out [] = $nItem;
      }
      
      if (!$sel)
        $out [$idx]['Selected'] = true;
      
      if ($this->isSubclass && $this->allowEmbed ())
        array_shift ($out);
      
      return $out;
    }
    // }}}
    
    // {{{ callbackCreate
    /**
     * Callback for Item-Creation
     *
     * @param object $Handle The object that was created
     * 
     * @access public
     * @return void
     **/
    public function callbackCreate ($Handle) { }
    // }}}
    
    // {{{ callbackUpdate
    /**
     * Callback for Item-Updates
     * 
     * @param object $Handle The object which was updated   
     * 
     * @access public
     * @return void
     **/
    public function callbackUpdate ($Handle) { }
    // }}}
  }

?>