/*
 * Attach Plugin for FCKeditor 2.6.3
 * Copyright (C) 2008 Shenjk (shjk813@126.com)
 *
 * == BEGIN LICENSE ==
 *
 * Licensed under the terms of any of the following licenses at your
 * choice:
 *http://www.shenjk.com
 *
 * == END LICENSE ==
 *
 * Scripts related to the Attach dialog window (see fck_attach.html).
 */

// Register the related command.
FCKCommands.RegisterCommand( 'Attach', new FCKDialogCommand( 'Attach', FCKLang.DlgAttachTitle, FCKPlugins.Items['Attach'].Path + 'fck_Attach.html', 450, 250 ) ) ;

// Create the "Attach" toolbar button.
var oAttachItem = new FCKToolbarButton( 'Attach', FCKLang.AttachBtn,  FCKLang.AttachBtnTooltip) ;
oAttachItem.IconPath = FCKPlugins.Items['Attach'].Path + 'images/Attach.gif' ;

FCKToolbarItems.RegisterItem( 'Attach', oAttachItem ) ;

var PlusPath=FCKPlugins.Items['Attach'].Path;
//--------------------------------------------------
function _Import(aSrc) {

  var vElement = document.createElement("script");
  vElement.type= "text/javascript";
  vElement.src= aSrc;

  var head=document.getElementsByTagName("head")[0];
  head.appendChild(vElement);

};

function _ImportCSS(aSrc) {
  var vElement = document.createElement("link");
  vElement.rel   = "stylesheet";
  vElement.type  = "text/css";
  vElement.href  = aSrc;
  //vElement.title= 'ddd';
  //vElement.disabled=false;

  var head=document.getElementsByTagName("head")[0];
  head.appendChild(vElement);
};

_Import(FCKConfig.PluginsPath + 'Attach/js/fck_Attach_inc.js');


var FCKAttachProcessor = FCKDocumentProcessor.AppendNew() ;

//hack to add the Attach css to FCKEditingArea.
FCKAttachProcessor.EditingArea_StartBefore = function ( html, secondCall )
{
  var sHeadExtra = '<link href="' + FCKConfig.PluginsPath + 'Attach/css/fck_Attach.css" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
  html = html.replace( FCKRegexLib.HeadCloser, sHeadExtra + '$&' ) ;
  return arguments;
}
FCKEditingArea.prototype.Start =  Inject(FCKEditingArea.prototype.Start, FCKAttachProcessor.EditingArea_StartBefore);

//hack and rewrite FCKConfig.ProtectedSource.Protect, for i do not wanna walk through twice.
FCKConfig.ProtectedSource.Protect = function( html )
{
  var codeTag = this._CodeTag ;
  function _Replace( protectedSource )
  {
    //check if it is the Attach object:
    if (protectedSource.match(/<object[\s\S]+?<\/object>/gi) && (protectedSource.indexOf(cAttachTypeAttrName+'=') >=0)) {
      var regexEmbed = new RegExp('<embed\\s+(.+?)><\/embed>', 'i');
      return '<'+cFckAttachElementName + ' '+ protectedSource.match(regexEmbed)[1] + '></'+cFckAttachElementName+'>';
    }

    var index = FCKTempBin.AddElement( protectedSource ) ;
    return '<!--{' + codeTag + index + '}-->' ;

  }

  for ( var i = 0 ; i < this.RegexEntries.length ; i++ )
  {
    html = html.replace( this.RegexEntries[i], _Replace ) ;
  }

  return html ;
}

//hacked FCKConfig.ProtectedSource.Revert
FCKAttachProcessor.ProtectedSource_RevertBefore = function ( html, clearBin )
{
  html = WrapObjectToAttach(html, cFckAttachElementName);
  return arguments;
}
FCKConfig.ProtectedSource.Revert = Inject(FCKConfig.ProtectedSource.Revert, FCKAttachProcessor.ProtectedSource_RevertBefore)

FCKAttachProcessor.ProcessDocument = function( aDocument )
{
  /* convert the source to WSWG design
  Sample code:
  */

  var aEmbeds = aDocument.getElementsByTagName( "a" ) ;

  var oEmbed ;
  var i = aEmbeds.length - 1 ;

  while ( i >= 0 && ( oEmbed = aEmbeds[i--] ) )
  {
    if (typeof(oEmbed.attributes[ cAttachTypeAttrName ]) != 'undefined') {

      var vTypeId = oEmbed.attributes[ cAttachTypeAttrName ].value ;
  
      if (isInt(vTypeId))
      {
        var oCloned = oEmbed.cloneNode( true ) ;
  
        var oImg = FCKDocumentProcessor_CreateFakeImage( 'FCK__Attach_'+vTypeId, oCloned ) ;
        oImg.setAttribute( '_fckAttach', 'true', 0 ) ;
  
        FCKAttachProcessor.RefreshView( oImg, oEmbed ) ;
  
        oEmbed.parentNode.replaceChild(oImg, oEmbed);
      }
    }
  }
}

FCKAttachProcessor.RefreshView = function( placeHolderImage, originalEmbed )
{

  if ( originalEmbed.getAttribute( 'width' ) > 0 )
    placeHolderImage.style.width = FCKTools.ConvertHtmlSizeToStyle( originalEmbed.getAttribute( 'width' ) ) ;

  if ( originalEmbed.getAttribute( 'height' ) > 0 )
    placeHolderImage.style.height = FCKTools.ConvertHtmlSizeToStyle( originalEmbed.getAttribute( 'height' ) ) ;
}

// Open the Attach Properties dialog on double click.
FCKAttachProcessor.OnDoubleClick = function( e )
{
  if ( e.tagName == 'IMG' && e.getAttribute('_fckAttach') == 'true' )
    FCKCommands.GetCommand( 'Attach' ).Execute() ;
}

FCK.RegisterDoubleClickHandler( FCKAttachProcessor.OnDoubleClick, 'IMG' ) ;


FCK.ContextMenu.RegisterListener( {
        AddItems : function( menu, tag, tagName )
        {
                // under what circumstances do we display this option
                if ( tagName == 'IMG' && tag.getAttribute( '_fckAttach' ) )
                {
                        // when the option is displayed, show a separator  the command
                        menu.AddSeparator() ;
                        // the command needs the registered command name, the title for the context menu, and the icon path
                        menu.AddItem( 'Attach', FCKLang.DlgAttachTitle, oAttachItem.IconPath ) ;
                }
        }}
);


FCKAttachProcessor.GetRealElementAfter = function( fakeElement, Result ) 
{
  if ( fakeElement.getAttribute('_fckAttach') )
  {
    if ( fakeElement.style.width.length > 0 )
        Result.width = FCKTools.ConvertStyleSizeToHtml( fakeElement.style.width ) ;

    if ( fakeElement.style.height.length > 0 )
        Result.height = FCKTools.ConvertStyleSizeToHtml( fakeElement.style.height ) ;
  }

  return Result ;
}
FCK.GetRealElement = Inject(FCK.GetRealElement, undefined, FCKAttachProcessor.GetRealElementAfter)

/*
  @desc  inject the function
  @param aOrgFunc     the original function to be injected.
  @param aBeforeExec  this is called before the execution of the aOrgFunc.
                      you must return the arguments if you wanna modify the value of the aOrgFunc's arguments .
  @param aAtferExec   this is called after the execution of the aOrgFunc.
                      you must add a result argument at the last argument of the aAtferExec function if you wanna 
                      get the result value of the aOrgFunc.
                      you must return the result if you wanna modify the result value of the aOrgFunc .

  @Usage  Obj.prototype.aMethod = Inject(Obj.prototype.aMethod, aFunctionBeforeExec[, aFunctionAtferExec]);
  @author  Aimingoo&Riceball

  eg:
  var doTest = function (a) {return a};
  function beforeTest(a) { alert('before exec: a='+a); a += 3; return arguments;};
  function afterTest(a, result) { alert('after exec: a='+a+'; result='+result); return result+5;};
  
  doTest = Inject(doTest, beforeTest, afterTest);
  
  alert (doTest(2));
  the result should be 10.

*/
function Inject( aOrgFunc, aBeforeExec, aAtferExec ) {
  return function() {
    if (typeof(aBeforeExec) == 'function') arguments = aBeforeExec.apply(this, arguments) || arguments;
    //convert arguments object to array
    var Result, args = [].slice.call(arguments); 
    args.push(aOrgFunc.apply(this, args));
    if (typeof(aAtferExec) == 'function') Result = aAtferExec.apply(this, args);
    return (typeof(Result) != 'undefined')?Result:args.pop();
  }
}
