
// depends on utils_1.1.js
(function(){

  var collapseSections = window.collapseSections = {

    config : {
      collapse : {
        // uses the values in  collapseSections.defaults
      }
    },

    defaults : {
      blockSel    : 'div.dropmenu',
      headSel     : 'h2.boxhd',
      excludeSel  : null,    // a CSS selector that defines a set of elements to subtract from the set defined by 'blockSel'.
      startOpen   : 0,       // specifies the first N items that should appear open by default.
      isVolatile : false,   // NOT IMPLEMENTED YET  (if the user *clicks* somewhere *outside* the block, the block should be closed)
      hoverOpen  : false,
      autoCloseDelay : 500,
      hoverOpenDelay  : 250,   // if set to number, the blocks toggle on mouseover/mouseout.
      // openFirst   : false,   // DEPRICATED!!! Use startOpen instead

      en : {
        openAll : 'Open all',
        closeAll : 'Close all'
      },
      is : {
        openAll : 'Opna alla',
        closeAll : 'Loka öllum'
      },
      showControls : 0,   // configures the display of 'open all'/'close all' control links.
                         // 0=disable;  1=display above;  2=display below;  3=above *and* below
      getCtrlSibling : function (_myBlock, _atBottom) { return _myBlock; }
    },


    _closeBlock : function (_myBlock, _byForce)
    {
      //;;;console.log('_closeBlock ', _myBlock.__hovered, _myBlock.__isOpen);
      if (_byForce || _myBlock.__isOpen)
      {
        DOM.replaceClass(_myBlock, _myBlock.__blockId+'-open', _myBlock.__blockId+'-closed', 1);
        _myBlock.__isOpen = false;
        EEvent.fire(_myBlock, 'CollapserClosed');
      }
    },

    _openBlock : function (_myBlock, _byForce)
    {
      //;;;console.log('_openBlock ', _myBlock.__hovered, _myBlock.__isOpen);
      if (_byForce || !_myBlock.__isOpen)
      {
        DOM.replaceClass(_myBlock, _myBlock.__blockId+'-closed', _myBlock.__blockId+'-open', 1);
        _myBlock.__isOpen = true;
        EEvent.fire(_myBlock, 'CollapserOpened');
      }
    },



    _toggleItem : function(e)
    {
      var _myBlock = this.myBlock,
          config = collapseSections.getCfg(_myBlock);
      if (!config.isVolatile && this.blur) { this.blur(); }
      collapseSections[(_myBlock.__isOpen) ? '_closeBlock' : '_openBlock'](_myBlock);
      return false;
    },


    allOpen  : function(_groupName) { return collapseSections._allChange((this.parentNode || _groupName), 1); },
    allClose : function(_groupName) { return collapseSections._allChange((this.parentNode || _groupName)); },

    _allChange : function(_groupName, _doOpen)
    {
      _groupName = _groupName.__groupName || _groupName;  // if _groupName.__groupName exists, then _groupName is really a _ctrlElm, Else a string
      var config = this.config[_groupName],
          _method = collapseSections[(_doOpen) ? '_openBlock' : '_closeBlock'];
      if (config)
      {
        for (var i=0,_myBlock; (_myBlock = config._theBlocks[i]); i++)
        {
          _method(_myBlock);
        }
      }
      return false;
    },



    _buildControls : function (_groupName, _lang)
    {
      var t = collapseSections.config[_groupName][_lang],
          _ctrlElm = DOM.node('<div class="collapsesections-ctrl '+ _groupName +'-ctrl"> \n</div>');
          _openLink  = DOM.node('<a href="#" class="openall">'+t.openAll+'</a>');
          _closeLink = DOM.node('<a href="#" class="closeall">'+t.closeAll+'</a>');

      _ctrlElm.__groupName = _groupName;

      DOM.prependChild(_openLink, _ctrlElm);
      DOM.appendChild(_closeLink, _ctrlElm);

      EEvent.add(_openLink, 'click', collapseSections.allOpen);
      EEvent.add(_closeLink, 'click', collapseSections.allClose);

      return _ctrlElm;
    },



    init : function(config)
    {
      if (config) { this.config = config; }

      for (var _blockId in this.config)
      {
        config = this.config[_blockId];

        // applying default config-values where needed
        if (config.openFirst != undefined) { config.startOpen = (config.openFirst) ? 1 : 0; } // ensure backwards compatibility with the old boolean syntax.
        for (var _key in this.defaults)
        {
          if (config[_key] == undefined) { config[_key] = this.defaults[_key]; }
        }

        var togglerFunction = GOO.bindAfter(collapseSections._toggleItem, null, config);

        var _theBlocks = DOM.get(config.blockSel);

        // prepare the blocks...
        var _exclBlocks = (config.excludeSel) ?  DOM.get(config.excludeSel) : null;

        for (var i = 0; i < _theBlocks.length; i++) 
        {
          var _myBlock = _theBlocks[i];
          if (!_exclBlocks || Array.indexOf(_exclBlocks, _myBlock) == -1)
          {

            _myBlock.__blockId = _blockId;
            var _isHeadChildOfBlock = false;
            var j = 0;
            var _myHead = DOM.get(config.headSel, _myBlock)[0];

            if (_myHead)
            {
              collapseSections.setCfg(_myBlock, config);

              var _theLink = _myHead;
              if (_theLink.tagName.lc() != 'a')
              {
                _theLink = DOM.get('a', _myHead)[0];
                if (!_theLink)
                {
                  _theLink = DOM.makeElement('<a href="#">'+DOM.innerText(_myHead)+'</a>');
                  _myHead.innerHTML = '';
                  _myHead.appendChild(_theLink);
                }
              }

              EEvent.add(_myBlock, 'mouseover', collapseSections._flagHover);
              EEvent.add(_myBlock, 'mouseout',  collapseSections._flagHover);

              if (config.hoverOpen)
              {
                EEvent.add(_myBlock, 'CollapserOpened', collapseSections._rigHoverOpenHandlers, null, 'remove');
                EEvent.add(_myBlock, 'CollapserClosed', collapseSections._rigHoverOpenHandlers);
              }
              else
              {
                EEvent.add(_theLink, 'click', togglerFunction);
              }

              if (config.isVolatile)
              {
                EEvent.add(_myBlock, 'CollapserOpened', collapseSections._rigAutoCloseHandlers);
                EEvent.add(_myBlock, 'CollapserClosed', collapseSections._rigAutoCloseHandlers, null, 'remove');
              }

              _theLink.myBlock = _myBlock;

              DOM.addClass(_myBlock, _blockId+'-active');
              collapseSections[(i < config.startOpen) ? '_openBlock' : '_closeBlock'](_myBlock, 1);

            }
          }

        }
        config._theBlocks = _theBlocks;


        // create and display control-links
        if (config.showControls && _theBlocks.length)
        {
          var _showAbove = (config.showControls != 2);
          var _showBelow = (config.showControls >= 2);
          var _lang = DOM.getLang( _theBlocks[0] );
          if (!_lang || !config[_lang]) { _lang = 'en'; }
          
          if (_showAbove)
          {
            DOM.insertBefore(this._buildControls(_blockId, _lang), config.getCtrlSibling(_theBlocks[0]));
          }
          if (_showBelow)
          {
            DOM.insertAfter(this._buildControls(_blockId, _lang), config.getCtrlSibling(_theBlocks[_theBlocks.length-1], 1));
          }
        }

      }
    },



    _flagHover : function (e) { this.__hovered = (e.type == 'mouseover'); },




    _rigHoverOpenHandlers : function (e, method)
    {
      //;;;console.log((method?'Remove':'Add') + ' HoverOpen handlers');
      method = EEvent[method || 'add'];
      method(this, 'mouseover', collapseSections._startDelayedOpen);
      method(this, 'mouseout',  collapseSections._cancelDelayedOpen);
      method(this, 'focusin',  collapseSections._startDelayedOpen);
      method(this, 'focusout', collapseSections._cancelDelayedOpen);
    },

    _hoverOpen : function (_myBlock) {
      collapseSections._openBlock(_myBlock);
      _myBlock._hoverOpenTimout = null;
    },

    _startDelayedOpen : function (e, hoverOpenDelay)
    {
      if (!this._hoverOpenTimout)
      {
        var _conf = collapseSections.getCfg(this);
        this._hoverOpenTimout = window.setTimeout(collapseSections._hoverOpen, _conf.hoverOpenDelay, this);
      }
    },

    _cancelDelayedOpen : function (e)
    {
      if (this._hoverOpenTimout)
      {
        clearTimeout(this._hoverOpenTimout);
        this._hoverOpenTimout = null;
      }
    },




    _rigAutoCloseHandlers : function (e, method)
    {
      //;;;console.log((method?'Remove':'Add') + ' AutoClose handlers');
      method = EEvent[method || 'add'];
      method(this, 'mouseout',  collapseSections._startDelayedClose);
      method(this, 'mouseover', collapseSections._cancelDelayedClose);
      method(this, 'focusout', collapseSections._startDelayedClose);
      method(this, 'focusin',  collapseSections._cancelDelayedClose);
    },
    
    _autoClose : function (_myBlock) {
      !_myBlock.__hovered  &&  collapseSections._closeBlock(_myBlock);
      _myBlock._autoCloseTimout = null;
    },

    _startDelayedClose : function (e)
    {
      if (!this._autoCloseTimout)
      {
        var _conf = collapseSections.getCfg(this);
        this._autoCloseTimout = window.setTimeout(collapseSections._autoClose, _conf.autoCloseDelay, this);
      }
    },

    _cancelDelayedClose : function (e)
    {
      if (this._autoCloseTimout)
      {
        clearTimeout(this._autoCloseTimout);
        this._autoCloseTimout = null;
      }
    },


    _cfgs : {},
    
    getCfg : function (obj)      { return obj ? this._cfgs[ obj.__guid ] : this._cfgs;  },

    setCfg : function (obj, cfg) { return this._cfgs[ DOM.guid(obj) ] = cfg; }



  };




})();

