/**
 * YAHOO.Plank.util
 * plank_util.js
 * 
 * Collection of commmon utils/wrappers for common actions
 * 
 * @package plank yui
 * @author  Mitchell Amihod 2008-07-19
 */
(function(){

  YAHOO.namespace('Plank.util');


  var Dom = YAHOO.util.Dom,
      Lang = YAHOO.lang,
      JSON = YAHOO.lang.JSON,
      Event = YAHOO.util.Event;
      
  //Set up short alias to oManager & makeit globally accessible.
  var oManager = YAHOO.Plank.util.oManager = new YAHOO.widget.OverlayManager();
    
  // ===============================================
  // = Scroller. Used instead of window.location. 
  // = I suppose I could just override window.location, but that feels rude.
  // ===============================================

  //The scroll anim. Set one up tied to for window. 
  //It won't actually do anything. Using it as a glorified calculator it feels like.
  var scrollAnim  =  new YAHOO.util.Scroll(window, {scroll:{}}, 1.0, YAHOO.util.Easing.easeOut);

  //Saves last position for scroll back.
  var scrollBack = false;
  /**
   * Scroll to a window position. If nothing passed in, then scroll to the scrollback position. 
   *
   * @param array Where to scroll to. If empty, then its a scroll back.
   * @param bool deault:false  To animate or not? Works ok, but not so well with other animations: ie: modal container opening.
   * @return void
   **/  
  YAHOO.Plank.util.scroll = function (scrollPos, animate) {
    
    animate = animate || false;

    //Believe it or not, scroll doesnt work on document body, nor on window (or didnt for me!)
    //Anyhow, subscribing to tween, and feeding values into window.scroll.
    scrollAnim.onTween.subscribe(
      function() {
        var pos = scrollAnim.getAttribute('scroll');      
        window.scroll(parseInt(pos[0],10),parseInt(pos[1],10));
      }
    );
    
    if( Lang.isUndefined(scrollPos) && Lang.isArray(scrollBack) ) {

      if(animate) {
        scrollAnim.attributes.scroll.from = [Dom.getDocumentScrollLeft(),Dom.getDocumentScrollTop()];
        scrollAnim.attributes.scroll.to = scrollBack;
        scrollAnim.animate();
      } else{
        window.scroll(scrollBack[0], scrollBack[1]);
      }
      
      scrollBack = false;

    } else if( Lang.isArray(scrollPos) ) {

      //get original position
      scrollBack = [Dom.getDocumentScrollLeft(),Dom.getDocumentScrollTop()];
      
      if(animate) {
        scrollAnim.attributes.scroll.to = scrollPos;
        scrollAnim.attributes.scroll.from = scrollBack;
        scrollAnim.animate();
      } else {
        window.scroll(scrollPos[0], scrollPos[1]);        
      } 
    }

    return;
    
  };
    
      

  /**
   * utility for container making. 
   * container is used generically by me to mean all yui container subclasses
   * 
   * customize to each projects needs, needed often enough to put it in with default for now.
   * @refactor  move into myUtil object
   * 
   * @param el    {string}  look for panel id string in overlay manager - not found? return new container
   *              {element} create new container from that el.
   *
   * @param oConfigs  {object} 
   *                 .conType Which container type to make. http://developer.yahoo.com/yui/container/
   *                          defaults to Ovelay
   * @return {container}  So you can chain
   **/
  YAHOO.Plank.util.container = function(el, oConfigs) {

    oConfigs = oConfigs || {};

    var oDefaults = {
      'conType' : 'Overlay', //This is personal setting- not needed by yui.
      'width'   : '600px',
      // 'height'  : '400px',
      'dragOnly': true // Make false to interact with drop targets
    };

    Lang.augmentObject(oConfigs, oDefaults);

    //Default to panel. Expected types map to those available YUI container types
    //Should be cased accordingly.
    var containerType = oConfigs.conType || oDefaults.conType;
    var container = null;

    //String? Look it up in oManager
    if(Lang.isString(el)) {
      container = oManager.find(el);      
    }

    //We use isValue here instead of inNull because of bug in overlayManager.find()
    // where it returns undefined instead of null when there's no overlays registered.
    if(!Lang.isValue(container)) {

      container = new YAHOO.widget[containerType](el, oConfigs);

      //Register it
      //YAHOO.log(container, 'info', 'register');
      oManager.register([container]);

    } else {
      //Apply any new configs
      container.cfg.applyConfig(oConfigs);
    }

    if(!Lang.isUndefined(oConfigs.source)) {
      var iframe = document.createElement('iframe');
      iframe.setAttribute('src', oConfigs.source);
      iframe.setAttribute('scrolling', 'no');
      iframe.setAttribute('height', parseInt(oConfigs.height, 10) - 55 );
      iframe.setAttribute('width', parseInt(oConfigs.width,10) - 30);
      container.setBody(iframe);
    }

    //Apply settings
    return container;

  };
  

  /**
   * Called when user clicks OK on cropping. 
   * @param entityId  
   * @param largeCrop Cropper instance
   * @param panel The panel, so we can close it on success of the ajax
   * @param el    The image thumb originally clicked on. In this case, it will be an IMG. We have to refresh this.
   * @return void
   **/
  var cropOk = function(entityId, largeCrop, panel, img) {

    var url = 'admin/submit/';
    
    var lCoords = largeCrop.getCropCoords();
    
    // Can make these into array? large[top]= and so forth?
    var postdata =  'entity=event_image&id='+entityId + 
                    '&large[top]=' + lCoords.top + '&large[left]=' + lCoords.left + '&large[height]=' + lCoords.height + '&large[width]=' + lCoords.width;
        
    var conn = YAHOO.util.Connect.asyncRequest('POST', url, {

      success: function(o) {
        if(o.responseText !== undefined) { 
          
          var resp = JSON.parse(o.responseText);
          
          if(resp.result == 1) {
            
            panel.hide();
            
            //Can add some sort of success cue.
            if(img && (img.tagName.toLowerCase()== 'img')) {
              //Refresh the img thumbnail.
              //img.src = img.src;
              updateThumb(img);
            }
          }
        }
      }
    }, postdata);
    
  };
  
  /**
   * Used on the event page, when cropping an image. This updates the thumbnail, and draws attention to the change.
   *
   **/
  function updateThumb(img)
  {    
    //Reload the new image
    //Fix the src for caching reasons.
    var newsrc = img.src.split('?',2);
    img.src = newsrc[0]+'?'+Dom.generateId();
    
    var proxyImg = img.cloneNode(false);
    proxyImg.id = Dom.generateId();
    
    document.body.appendChild(proxyImg);
    
    Dom.setStyle(proxyImg,'position', 'absolute');
    Dom.setXY(proxyImg, Dom.getXY(img));
    
    //need to use img_o values, since img height isn't known from proxy img being inserted dynamically
    var animAttribs = {
      opacity: {from: 0, to: 1},
      height: {from:img.height*2, to: img.height},
      width: {from:img.width*2, to: img.width} 
    };
    
    var anim = new YAHOO.util.Anim(proxyImg, animAttribs, 1.0, YAHOO.util.Easing.easeOut);
    
    anim.onComplete.subscribe(function() {
      proxyImg.parentNode.removeChild(proxyImg);
    });

    anim.animate();
    
  }
  
  /**
   * Set up the image cropping
   *
   * @todo can use some refactoring now that we've added in the overrides for previous crop
   * basically enumerate the types of croppers we want in an array, andloop to create.
   **/
  YAHOO.Plank.util.imagecropper = function(el) {
    
    var names = {
      CROP_PANEL_ID: 'plank-imagecropper',
      CROP_CLASS: 'plank-imagecrop',
      ORIGINAL_IMAGE: 'cropper.jpg',
      IMG_THUMB_ID: 'img-cropper-thumb',
      IMG_CROP_1_ID       : 'img-cropper-large'
    };
    
    //Check if the cropper has already been rendered & loaded?
    //This will redisplay it with whatever last settings were.
    if(Lang.isValue(oManager.find(names.CROP_PANEL_ID))) {
      oManager.find(names.CROP_PANEL_ID).show();
      return true;
    }
    
    var cropInfo = YAHOO.Plank.bb.cropInfo || false;
    
    var imagePath = el.src.substring( el.src.lastIndexOf('/')+1 , 0 );
    var eventId = window.location.href.split('/').pop();
    var largeImage = Dom.get(names.IMG_CROP_1_ID);

    //Default size configs
    var sizes = {
      'large': {
        'initialXY': [0,0],
        "initHeight": 375,
        'initWidth': 620
      }
    };
    
    var targetRatio = sizes.large.initWidth/sizes.large.initHeight;

    //Modify defaults based on image if certain conditions: ie: not tall enought
    if(largeImage.height < sizes.large.initHeight) {        
        sizes.large.initWidth = parseInt(largeImage.height * targetRatio,10);
        sizes.large.initHeight = largeImage.height;
    }
    //Any defaults to override?
    for(ctype in cropInfo) {
      if(Lang.hasOwnProperty(cropInfo, ctype)) {
          //Compensate for old data.
          if(Lang.isUndefined(sizes[ctype])){
              continue;
          }

          //We should just ignore these - they represent the old settings.
          if((cropInfo[ctype].width/cropInfo[ctype].height).toFixed(3) > targetRatio.toFixed(1)) {
            continue;
          }
          
        sizes[ctype].initialXY = [cropInfo[ctype].left, cropInfo[ctype].top];
        sizes[ctype].initHeight = cropInfo[ctype].height;
        sizes[ctype].initWidth = cropInfo[ctype].width;
      }
    }      

    var croppers = {};

    croppers.large = new YAHOO.widget.ImageCropper(largeImage, {
          initHeight: sizes.large.initHeight,
          initWidth: sizes.large.initWidth,
          ratio: true,
          initialXY: sizes.large.initialXY, keyTick: 5, shiftKeyTick: 50
    });

    Dom.removeClass(Dom.get(names.CROP_PANEL_ID), 'hide');
    var cropCon = this.container(names.CROP_PANEL_ID, 
      {
        'conType' : 'Dialog',
        'modal'   : true,
        'fixedcenter':true,
        'width' : '640px',
        'visible' : true,
        'buttons' : [ 
                  {
                    text:"OK", 
                    isDefault:true, 
                    handler: function() {
                      // YAHOO.log(arguments);
                      cropOk(eventId, croppers.large, arguments[1], el);
                    }
                  }, 
                  {
                    text:"Cancel", 
                    handler: function() {this.hide();}
                  } 
                ]
      }
    );

    // Show/Hide events. Right now, just for the scrolls, but could perform other actions here. 
    cropCon.hideEvent.subscribe(function() {
      this.scroll();
    }, this, true);

    //Subscribe to the Show event, to scroll to
    cropCon.showEvent.subscribe(function() {
      this.scroll([0,0]);
    }, this, true);

    // @problem - applying cropper makes panel height collapse. maybe a spacer img? or maybe css issue?
    // @solution turned out when making the module dynamically. If i defined the cropper markup in html, works fine.
    cropCon.render();
    //And now remove fixed center
    cropCon.cfg.setProperty('fixedcenter', false);
    cropCon.cfg.setProperty('y', 0);

  };
  
  
  /*
  *Trigger motion and animation together.
  */
  var animate = function(toAnim, motionAttribs, animAttribs) {
    
    var oAnims = {};
    
  	oAnims.motion = new YAHOO.util.Motion(toAnim, motionAttribs, 0.7, YAHOO.util.Easing.easeOutStrong);
  	oAnims.anim = new YAHOO.util.Anim(toAnim,animAttribs, 0.9, YAHOO.util.Easing.bounceOut );		

  	oAnims.motion.onStart.subscribe(
  		function() {
  			oAnims.anim.animate();
  		}
  	);

  	oAnims.motion.animate();
  	
  	return oAnims;
  };

  
  /**
   * remove el function. 
   * right now, used for removing an item from a DnD list. 
   *
   * @param el HTMLElement
   * @return void
   **/
  YAHOO.Plank.util.remove = function(el) {

			var rpoint = Dom.getXY(el);

			var xy_anim = [rpoint[0] + 235, rpoint[1] + -100]; 
			var points = { to: xy_anim, control: [  [rpoint[0] + 300, rpoint[1] + 100] ] } ;
			
			var motionAttribs = { points:  points };
			var animAttribs = {opacity: { to: 0 }, height:{to:0} };
			
			var anims = animate(el, motionAttribs, animAttribs);
    
      anims.anim.onComplete.subscribe(
        function() {
          el.parentNode.removeChild(el);
        }
      );
      //el.parentNode.removeChild(el);    
  };

  YAHOO.register("plank_util", YAHOO.Plank.util, {version: "1.2", build: "1"}); 

})();
