/* global Ext */
/*
 * @class Ext.ux.Media,
 *        Ext.ux.MediaComponent (xtype: media),
 *        Ext.ux.MediaPanel     (xtype: mediapanel)
 *        Ext.ux.MediaWindow
 *
 * Version:  1.0
 * Author: Doug Hendricks. doug[always-At]theactivegroup.com
 * Copyright 2007-2008, Active Group, Inc.  All rights reserved.
 *
 ************************************************************************************
 *   This file is distributed on an AS IS BASIS WITHOUT ANY WARRANTY;
 *   without even the implied warranty of MERCHANTABILITY or
 *   FITNESS FOR A PARTICULAR PURPOSE.
 ************************************************************************************

 License: ux.Media classes are licensed under the terms of
 the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
 that the code/component(s) do NOT become part of another Open Source or Commercially
 licensed development library or toolkit without explicit permission.

 Donations are welcomed: http://donate.theactivegroup.com

 License details: http://www.gnu.org/licenses/lgpl.html

 Notes: the <embed> tag is NOT used(or necessary) in this implementation

 Version:  1.0  Height/Width now honors inline style as well,
           Added Component::mediaEl(eg: 'body', 'el') for targeted media rendering.
           Added scale and status macros.

 Version:  Rc1
           Adds inline media rendering within markup: <div><script>document.write(String(new Ext.ux.Media(mediaCfg)));</script></div>
           New extensible classes :
              ux.Media
              ux.MediaComponent
              ux.MediaPanel

           Solves the Firefox reinitialization problem for Ext.Components with embedded <OBJECT> tags
           when the upstream DOM is reflowed.

           See Mozilla https://bugzilla.mozilla.org/show_bug.cgi?id=262354

 Version:  .31 Fixes to canned WMV config.
 Version:  .3  New class Heirarchy.  Adds renderMedia(mediaCfg) method for refreshing
               a mediaPanels body with a new/current mediaCfg.
 Version:  .2  Adds JW FLV Player Support and enhances mediaClass defaults mechanism.
 Version:  .11 Modified width/height defaults since CSS does not seem to
                honor height/width rules
 Version:  .1  initial release

 mediaCfg: {Object}
     { mediaType : mediaClass defined by ux.Media.mediaTypes[mediaClass]
      ,url       : Url resource to load when rendered
      ,requiredVersion : may specify a specific player/plugin version (for use with inline plugin updates where implemented)
      ,loop      : (true/false) (@macro enabled)
      ,scripting : (true/false) (@macro enabled)
      ,start     : (true/false) (@macro enabled)
      ,volume    : (number%, default: 20 ) audio volume level % (@macro enabled)
      ,height    : (default: 100%) (@macro enabled)
      ,width     : (default: 100%) (@macro enabled)
      ,scale     : (default: 1) (@macro enabled)
      ,status    : (default: false) (@macro enabled)
      ,autoSize  : (true/false) If true the rendered <object> consumes 100% height/width of its
                     containing Element.  Actual container height/width are available to macro substitution
                     engine.
      ,controls  : optional: show plugins control menu (true/false) (@macro enabled)
      ,unsupportedText: (String,DomHelper cfg) Text to render if plugin is not installed/available.
      ,listeners  : {"mouseover": function() {}, .... } DOM listeners to set each time the Media is rendered.
      ,params   : { }  members/values unique to Plugin provider
     }

*/
(function(){

    /*
    * Base Media Class
    */

    Ext.ux.Media = function(config){
        Ext.apply(this,config||{});
        this.toString = this.mediaMarkup;
        this.initMedia();
        };

    var ux = Ext.ux.Media;

    ux.mediaTypes =
     {
       "PDF" : Ext.apply({
                tag     :'object'
               ,cls     : 'x-media x-media-pdf'
               ,type    : "application/pdf"
               ,style   :{position:'absolute',top:'0px',left:'0px','z-index':11002}
               ,data    : "@url"
               ,autoSize:true
               ,params  : { src : "@url" }

               },Ext.isIE?{classid :"CLSID:CA8A9780-280D-11CF-A24D-444553540000"}:false)


      ,"WMV" : Ext.apply(
              {tag      :'object'
              ,cls      : 'x-media x-media-wmv'
              //,type      :'video/x-ms-wmv'
              ,type     : 'application/x-mplayer2'
              ,standby  : 'Loading Microsoft Windows Media Player components...'
              ,data     : "@url"
              ,params  : {
                  src          : "@url"
                 ,url          : "@url"
                 ,autostart    : "@start"
                 ,showControls : "@controls"
                 ,showStatusBar: "@status"

               }
               },Ext.isIE?{
                   //classid :"CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"
                   classid :"CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95" //default for WMP installed w/Windows
                   }:false)

       /* WMV Interface Notes
        * On IE only, to retrieve the object interface (for controlling player via JS)
        * use mediaComp.getInterface().object.controls
        *
        * For all other browsers use: mediaComp.getInterface().controls
        Related DOM attributes for WMV:
        DataFormatAs :
        Name :
        URL :
        OpenState:6
        PlayState:0
        Controls :
        Settings :
        CurrentMedia:null
        MediaCollection :
        PlaylistCollection :
        VersionInfo:9.0.0.3008
        Network :
        CurrentPlaylist :
        CdromCollection :
        ClosedCaption :
        IsOnline:false
        Error :
        Status :
        Dvd :
        Enabled:true
        FullScreen:false
        EnableContextMenu:true
        UiMode:full
        StretchToFit:false
        WindowlessVideo:false
        IsRemote:false
        */

       ,"SWF" :  Ext.apply({
                  tag      :'object'
                 ,cls      : 'x-media x-media-swf'
                 ,type     : 'application/x-shockwave-flash'
                 ,data     : "@url"
                 ,scripting: 'sameDomain'
                 ,loop     :  true
                 ,start    :  false
                 ,unsupportedText : {cn:['The Adobe Flash Player{0}is required.',{tag:'br'},{tag:'a',cn:'The free download is available here.',href:'http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash',target:'_flash'}]}
                 ,params   : {
                      movie     : "@url"
                     ,menu      : "@controls"
                     ,play      : "@start"
                     ,quality   : "high"
                     ,allowscriptaccess : "@scripting"
                     ,bgcolor   : "#FFFFFF"
                     ,wmode     : "opaque"
                     ,loop      : "@loop"
                    }

                },Ext.isIE?{classid :"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
                           ,codebase:"http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"
                           }:false)
        ,"JWP" :  Ext.apply({
              tag      :'object'
             ,cls      : 'x-media x-media-swf x-media-flv'
             ,type     : 'application/x-shockwave-flash'
             ,data     : "@url"
             ,loop     :  false
             ,start    :  false
             ,params   : {
                 movie     : "@url"
                ,flashVars : {
                               autostart:'@start'
                              ,repeat   :'@loop'
                              ,height   :'@height'
                              ,width    :'@width'
                              ,id       : '@id'
                              }
                }

        },Ext.isIE?{classid :"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"}:false)
        /* QuickTime */
        ,"MOV" : Ext.apply({
                  tag      :'object'
                 ,cls      : 'x-media x-media-mov'
                 ,type     : "video/quicktime"
                 ,style     :{position:'relative'}
                 ,data     : "@url"
                 ,scripting: false
                 ,loop     : false
                 ,scale    : 1 // ( .5, 1, 2 , ToFit, Aspect )
                 ,params   : {
                       src          : "@url"
                      ,autoplay     : "@start"
                      ,controller   : "@controls"
                      ,enablejavascript : "@scripting"
                      ,loop         :'@loop'
                      ,scale        :'@scale'
                      ,volume       :'@volume'
                    }
                 },Ext.isIE?
                        {  classid      :'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B'
                          ,codebase     :'http://www.apple.com/qtactivex/qtplugin.cab#version=7,2,1,0'
                          ,type         : 'application/x-oleobject'

                    }:false)
        ,"QT-ANY" : Ext.apply({
                       tag      : 'object'
                      ,cls      : 'x-media x-media-audio x-media-mpeg'
                      ,type     : "video/quicktime"
                      ,style    : {zoom:1}
                      ,data     : '@url'
                      ,params   : {
                           src          : "@url"
                          ,autoplay     : "@start"
                          ,controller   : "@controls"
                          ,enablejavascript : "@scripting"
                          ,loop         :'@loop'
                          ,scale        :'@scale'
                          ,volume       :'@volume'
                          ,QTSRC        : '@url'
                       }

                     },Ext.isIE?
                          { classid      :'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B'
                           ,codebase     :'http://www.apple.com/qtactivex/qtplugin.cab'
                           ,type         : 'application/x-oleobject'

                   }:false)
        ,"QTMIDI" : Ext.apply({
                      tag      : 'object'
                     ,cls      : 'x-media x-media-audio x-media-midi'
                     ,type     : "audio/midi"
                     //,style    : {overflow:'auto'}
                     ,data     : "@url"
                     ,params   : {
                                src          : "@url"
                               ,autoplay     : "@start"
                               ,controller   : "@controls"
                               ,enablejavascript : "@scripting"
                               ,loop         :'@loop'
                               ,scale        :'@scale'
                               ,volume       :'@volume'
                      }

                    },Ext.isIE?
                     { classid      :'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B'
                      ,codebase     :'http://www.apple.com/qtactivex/qtplugin.cab#version=7,2,1,0'
                      ,type         : 'application/x-oleobject'

                      }:false)

        ,"QTMP3" : Ext.apply({
               tag      : 'object'
              ,cls      : 'x-media x-media-audio x-media-mpeg'
              ,type     : "audio/mpeg"
              ,data     : '@url'
              ,params   : {
                   src          : "@url"
                  ,autoplay     : "@start"
                  ,controller   : "@controls"
                  ,enablejavascript : "@scripting"
                  ,loop         :'@loop'
                  ,scale        :'@scale'
                  ,volume       :'@volume'
               }

             },Ext.isIE?
                  { classid      :'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B'
                   ,codebase     :'http://www.apple.com/qtactivex/qtplugin.cab'
                   ,type         : 'application/x-oleobject'

                   }:false)

       ,"QTWAV" : Ext.apply({
                 tag      : 'object'
                ,cls      : 'x-media x-media-audio x-media-wav'
                ,type     : "audio/wav"
                ,data     : '@url'
                ,params   : {
                       src          : "@url"
                      ,autoplay     : "@start"
                      ,controller   : "@controls"
                      ,enablejavascript : "@scripting"
                      ,loop         :'@loop'
                      ,scale        :'@scale'
                      ,volume       :'@volume'
                 }
           },Ext.isIE?
                { classid      :'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B'
                 ,codebase     :'http://www.apple.com/qtactivex/qtplugin.cab'
                 ,type         : 'application/x-oleobject'
                 }:false)
         /* QT references:
          * http://developer.apple.com/documentation/quicktime/Conceptual/QTScripting_JavaScript/aQTScripting_Javascro_AIntro/chapter_1_section_1.html
          */
        ,"REAL" : Ext.apply({
                    tag     :'object'
                   ,cls     : 'x-media x-media-real'
                   ,type    : "audio/x-pn-realaudio"
                   ,data    : "@url"
                   ,standby : "Loading Real Media Player components..."
                   ,params   : {
                              src        : "@url"
                             ,autostart  : "@start"
                             ,controller : "@controls"
                             ,controlls  : "@controls"
                             ,loop       : "@loop"
                             ,console    : "TES"
                             }

                    },Ext.isIE?{classid :"clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"}:false)

        ,"SVG" : {
                  tag      : 'object'
                 ,cls      : 'x-media x-media-img x-media-svg'
                 ,type     : "image/svg+xml"
                 ,data     : "@url"
        }
        ,"GIF" : {
                  tag      : 'img'
                 ,cls      : 'x-media x-media-img x-media-gif'
                 ,src     : "@url"
        }
        ,"JPEG" : {
                  tag      : 'img'
                 ,cls      : 'x-media x-media-img x-media-jpeg'
                 ,src     : "@url"
        }
        ,"JP2" :{
                          tag      : 'object'
                         ,cls      : 'x-media x-media-img x-media-jp2'
                         ,type     : "image/jpeg2000-image"
                         ,data     : "@url"
                }

        ,"PNG" : {
                  tag      : 'img'
                 ,cls      : 'x-media x-media-img x-media-png'
                 ,src     : "@url"
        }
        ,"HTM" : {
                  tag      : 'iframe'
                 ,cls      : 'x-media x-media-html'
                 ,frameBorder : 0
                 ,style    : {overflow:'auto',width:'100%',height:'100%'}
                 ,src     : "@url"
        }
        ,"TXT" : {
                  tag      : 'object'
                 ,cls      : 'x-media x-media-text'
                 ,type     : "text/plain"
                 ,style    : {overflow:'auto',width:'100%',height:'100%'}
                 ,data     : "@url"
        }
        ,"SILVER" : {
              tag      : 'object'
             ,cls      : 'x-media x-media-silverlight'
             ,type      :"application/x-silverlight"
             ,data     : "@url"
        }

        ,"OFFICE" : {
              tag      : 'object'
             ,cls      : 'x-media x-media-office'
             ,type      :"application/x-msoffice"
             ,data     : "@url"
        }
        ,"XML" : {
              tag      : 'iframe'
             ,cls      : 'x-media x-media-xml'
             ,style    : {overflow:'auto'}
             ,src     : "@url"
        }


    };


    //Ext.apply(ux.prototype , {
    Ext.extend(ux, Object , {

         mediaObject     : null,
         mediaCfg        : null,
         mediaVersion    : null,
         requiredVersion : null,
         unsupportedText : null,


         /* Component Plugins Interface
           extends the Component instance with ux.Media.* interfaces
         */
         init        : function(component){

            if(component && this.getEl === undefined){
                Ext.applyIf(component,this);
            }

         },

         initMedia      : function(){ },

         onBeforeMedia  : function(mediaCfg, ct, domPosition ){

              var m = mediaCfg || this.mediaCfg, mt;

              if( m && (mt = this.getMediaType(m.mediaType)) ){
                  m.autoSize = m.autoSize || mt.autoSize===true;
                  //m.autoSize = (m.autoSize === undefined? mt.autoSize===true:m.autoSize===true);

                  //Calculate parent container size for macros (if available)
                  if(m.autoSize && (ct = Ext.isReady?Ext.get(ct||this.lastCt):null)){
                    m.height = ct.getHeight(true) || this.assert(m.height,'auto');
                    m.width  = ct.getWidth(true)  || this.assert(m.width ,'auto');
                  }

               }

        },

         onAfterMedia   : function(){
             //Reattach any DOM Listeners after rendering.
             var L = this.mediaCfg?this.mediaCfg.listeners:null;
             if(L && this.mediaObject){  this.mediaObject.on(L); }
         },

         getMediaType: function(type){
             return ux.mediaTypes[type];
         },

         assert : function(v,def){
              v= typeof v === 'function'?v.call(v.scope||null):v;
              return Ext.value(v ,def);
         },

         mediaMarkup : function(mediaCfg, width, height, ct){

             mediaCfg = mediaCfg ||this.mediaCfg;

             if(!mediaCfg){return '';}

             var m= Ext.apply({url:false,autoSize:false}, mediaCfg); //make a copy

             m.url = this.assert(m.url,false);

             if( m.url ){

                 var value,p, El = Ext.Element;

                 var media = Ext.apply({}, this.getMediaType(this.assert(m.mediaType,false)) || false );

                 var params = Ext.apply(media.params||{},m.params || {});

                 for(var key in params){
                    if(params.hasOwnProperty(key)){
                      m.children || (m.children = []);

                      p = this.assert(params[key],null);
                      if(p !== null){
                         m.children.push({tag:'param'
                                         ,name:key
                                         ,value: typeof p === 'object'?Ext.urlEncode(p):encodeURI(p)
                                         });
                      }
                    }
                 }
                 delete   media.params;

                 //Convert height and width to inline style to avoid issues with display:none;
                 m.style = this.assert(Ext.apply(media.style || {}, m.style || {}) , {});
                 delete media.style;

                 m.height = this.assert(height || m.height || media.height, null);
                 m.width  = this.assert(width  || m.width  || media.width , null);

                 //childNode Text if plugin/object is not installed.
                 media.html = this.assert(m.unsupportedText|| this.unsupportedText || media.unsupportedText,null);

                 m = Ext.apply({tag:'object'},m,media);

                 Ext.apply(m.style , {
                      height:El.addUnits( (m.autoSize ? '100%' : m.height || m.style.height || '100%' ),El.prototype.defaultUnit),
                      width :El.addUnits( (m.autoSize ? '100%' : m.width || m.style.width ||'100%'),El.prototype.defaultUnit)
                      });

                 m.id || (m.id = Ext.id());

                 var _macros= {
                   url       : m.url || ''
                  ,height    : parseInt(m.height,10)||100
                  ,width     : parseInt(m.width,10)||100
                  ,scripting : this.assert(m.scripting,false)
                  ,controls  : this.assert(m.controls,false)
                  ,scale     : this.assert(m.scale,1)
                  ,status    : this.assert(m.status,false)
                  ,start     : this.assert(m.start, false)
                  ,loop      : this.assert(m.loop, false)
                  ,volume    : this.assert(m.volume, 20)
                  ,id        : m.id
                 };

                 delete   m.url;
                 delete   m.mediaType;
                 delete   m.controls;
                 delete   m.status;
                 delete   m.start;
                 delete   m.loop;
                 delete   m.scale;
                 delete   m.scripting;
                 delete   m.volume;
                 delete   m.autoSize;
                 delete   m.params;
                 delete   m.unsupportedText;
                 delete   m.renderOnResize;
                 delete   m.listeners;
                 delete   m.height;
                 delete   m.width;


                 return Ext.DomHelper.markup(m)
                   .replace(/(%40url|@url)/g          ,_macros.url)
                   .replace(/(%40start|@start)/g      ,_macros.start+'')
                   .replace(/(%40controls|@controls)/g,_macros.controls+'')
                   .replace(/(%40scale|@scale)/g      ,_macros.scale+'')
                   .replace(/(%40status|@status)/g    ,_macros.status+'')
                   .replace(/(%40id|@id)/g            ,_macros.id+'')
                   .replace(/(%40loop|@loop)/g        ,_macros.loop+'')
                   .replace(/(%40volume|@volume)/g    ,_macros.volume+'')
                   .replace(/(%40scripting|@scripting)/g ,_macros.scripting+'')
                   .replace(/(%40width|@width)/g      ,_macros.width+'')
                   .replace(/(%40height|@height)/g    ,_macros.height+'');

             }else{
                 var unsup = this.assert(m.unsupportedText|| this.unsupportedText || media.unsupportedText,null);
                 unsup = unsup ? Ext.DomHelper.markup(unsup): null;
                 return String.format(unsup || 'Media Configuration/Plugin Error',' ',' ');
             }

         }
          /*
          *  This method updates the target Element with a new mediaCfg object,
          *  or supports a refresh of the target based on the current mediaCfg object
          *  This method may be invoked inline (in Markup) before the DOM is ready
          *  param position indicate the DomHeper position for Element insertion (ie 'afterbegin' the default)
          */
          ,renderMedia : function(mediaCfg, ct, domPosition , w , h){
              if(!Ext.isReady){
                  Ext.onReady(this.renderMedia.createDelegate(this,Array.prototype.slice.call(arguments,0)));
                  return;
              }
              var mc = (this.mediaCfg = mediaCfg || this.mediaCfg) ;
              ct = Ext.get(ct || this.lastCt || (this.mediaObject?this.mediaObject.dom.parentNode:null));

              this.onBeforeMedia.call(this, mc, ct, domPosition , w , h);

              if(ct){
                  var markup;

                  if(ct && mc && (markup = this.mediaMarkup(mc, w, h, ct))){
                     this.clearMedia();
                     ct.update(markup);
                     this.mediaObject = Ext.get(ct.dom.firstChild);
                  }
              }
              this.onAfterMedia(ct);
              this.lastCt = ct;

          }
          //Remove an existing mediaObject from the DOM.
          ,clearMedia : function(){
            if(Ext.isReady && this.mediaObject){
                this.mediaObject.removeAllListeners();
                this.mediaObject.remove();
            }
            this.mediaObject = null;
          }
         ,getInterface  : function(){
              return this.mediaObject?this.mediaObject.dom||null:null;
          }

         ,detectVersion  : Ext.emptyFn

    });
    //Private adapter class
    var mediaComponentAdapter = function(){};
    //Ext.apply(mediaComponentAdapter.prototype, {
    Ext.extend(mediaComponentAdapter, Object, {

         hideMode      : !Ext.isIE?'nosize':'display'

        ,animCollapse  : false

        ,visibilityCls : !Ext.isIE ?'x-hide-nosize':null

        ,autoScroll    : false

        ,shadow        : false

        ,bodyStyle     : {position: 'relative'}

        ,resizeMedia   : function(comp, w, h){
            var mc = this.mediaCfg;

            if(mc && this.boxReady){

                // Ext.Window.resizer fires this event a second time
                if(arguments.length > 3 && (!this.mediaObject || mc.renderOnResize )){
                    this.refreshMedia(this[this.mediaEl]);
                }
            }

         }

        ,adjustVisibility : function(els){
            els = [].concat(els||[]);
            var El = Ext.Element;
            var mode = this.visibilityCls || El[this.hideMode.toUpperCase()] || El.VISIBILITY;
            Ext.each(els, function(el){
                    if(el){el.setVisibilityMode(mode);}
               });

            if(this.loadMask){
              this.loadMask = new Ext.LoadMask(this.bwrap||this.getEl(),Ext.apply({},this.loadMask));
              this.loadMask.removeMask = false;
            }
            if(this.mediaCfg.renderOnResize ){
                this.on('resize', this.resizeMedia, this);
            }else{
                this.renderMedia(this.mediaCfg,this[this.mediaEl] || this.getEl());
            }
        }

        ,doAutoLoad : Ext.emptyFn

        ,refreshMedia  : function(target){
            if(this.mediaCfg) {this.renderMedia(null,target);}
        }
        ,loadMask  : false

    });

    /* Generic Media BoxComponent */
    Ext.ux.MediaComponent = Ext.extend(Ext.BoxComponent, {
        ctype           : "Ext.ux.MediaComponent",
        autoEl          : 'div',
        cls             : "x-media-comp",
        mediaEl         : 'el',   //the containing target element for the media,
        getId           : function(){
            return this.id || (this.id = "media-comp" + (++Ext.Component.AUTO_ID));
        },
        initComponent   : function(){
            this.initMedia();

            Ext.ux.MediaComponent.superclass.initComponent.apply(this,arguments);
        },

        afterRender     :  function(){

            this.setAutoScroll();

            Ext.ux.MediaComponent.superclass.afterRender.apply(this,arguments);

            this.adjustVisibility(this.getEl());

        },
        beforeDestroy   : function(){
            this.clearMedia();
            Ext.ux.MediaComponent.superclass.beforeDestroy.call(this);
         },
         //private
        setAutoScroll   : function(){
            if(this.rendered && this.autoScroll){
                this.getEl().setOverflow('auto');
            }
        }

    });

    //Inherit the Media.Flash class interface
    Ext.apply(Ext.ux.MediaComponent.prototype, Ext.ux.Media.prototype);
    Ext.apply(Ext.ux.MediaComponent.prototype, mediaComponentAdapter.prototype);
    Ext.reg('media', Ext.ux.MediaComponent);

    ux.Panel = Ext.extend( Ext.Panel, {

         ctype         : "Ext.ux.Media.Panel"
        ,cls           : "x-media-panel"
        ,mediaEl       : 'body'   //the containing target element for the media
        ,initComponent : function(){

            this.initMedia();
            delete this.html;
            this.contentEl = null;
            this.items = null;

            ux.Panel.superclass.initComponent.call(this);
        }
        ,onRender  : function(){

              ux.Panel.superclass.onRender.apply(this, arguments);
              this.adjustVisibility ([this[this.collapseEl],this.floating? null: this.getActionEl()]);

         }
        ,beforeDestroy : function(){
            this.clearMedia();
            ux.Panel.superclass.beforeDestroy.call(this);
         }
    });

    //Inherit the Media class interface
    Ext.apply(ux.Panel.prototype,ux.prototype);
    Ext.apply(ux.Panel.prototype, mediaComponentAdapter.prototype);
    Ext.reg('mediapanel', Ext.ux.MediaPanel = ux.Panel);

    ux.Window = Ext.extend( Ext.Window ,{

         cls           : "x-media-window"
        ,ctype         : "Ext.ux.Media.Window"
        ,mediaEl       : 'body'   //the containing target element for the media
        ,initComponent : function(){

            this.initMedia();
            delete this.html;
            this.contentEl = null;
            this.items = null;

            ux.Window.superclass.initComponent.call(this);
        }

        ,onRender  : function(){
           ux.Window.superclass.onRender.apply(this, arguments);
           this.adjustVisibility ([this[this.collapseEl]],this.floating? null: this.getActionEl()); //,this.mask
         }
         ,beforeDestroy : function(){
            this.clearMedia();
            ux.Window.superclass.beforeDestroy.call(this);
         }

    });

    //Inherit the Media class interface
    Ext.apply(ux.Window.prototype, ux.prototype);
    //then the Adaptor
    Ext.apply(ux.Window.prototype, mediaComponentAdapter.prototype);
    Ext.ux.MediaWindow = ux.Window;


    Ext.onReady(function(){
        //Generate CSS Rules if not defined in markup
        var CSS = Ext.util.CSS, rules=[];
        CSS.getRule('.x-media') || (rules.push('.x-media{width:100%;height:100%;display:block;overflow:none;}'));
        CSS.getRule('.x-media-mask') || (rules.push('.x-media-mask{position:absolute;top:0px;left:0px;background-color:transparent;width:auto;height:auto;zoom:1;}'));
        //default Rule for IMG:  h/w: auto;
        CSS.getRule('.x-media-img') || (rules.push('.x-media-img{background-color:transparent;width:auto;height:auto;zoom:1;}'));
        CSS.getRule('.x-hide-nosize .x-media') || (rules.push('.x-hide-nosize,.x-hide-nosize .x-media {height:0!important;width:0!important;border:none!important;}'));

        if(!!rules.length){
             CSS.createStyleSheet(rules.join(''));
        }

    });

  /* overrides add a third visibility feature to Ext.Element:
    * Now an elements' visibility may be handled by application of a custom (hiding) CSS className.
    * The class is removed to make the Element visible again
    */

    Ext.apply(Ext.Element.prototype, {
      setVisible : function(visible, animate){
            if(!animate || !Ext.lib.Anim){
                if(this.visibilityMode === Ext.Element.DISPLAY){
                    this.setDisplayed(visible);
                }else if(this.visibilityMode === Ext.Element.VISIBILITY){
                    this.fixDisplay();
                    this.dom.style.visibility = visible ? "visible" : "hidden";
                }else {
                    this[visible?'removeClass':'addClass'](String(this.visibilityMode));
                }

            }else{
                // closure for composites
                var dom = this.dom;
                var visMode = this.visibilityMode;

                if(visible){
                    this.setOpacity(.01);
                    this.setVisible(true);
                }
                this.anim({opacity: { to: (visible?1:0) }},
                      this.preanim(arguments, 1),
                      null, .35, 'easeIn', function(){

                         if(!visible){
                             if(visMode === Ext.Element.DISPLAY){
                                 dom.style.display = "none";
                             }else if(visMode === Ext.Element.VISIBILITY){
                                 dom.style.visibility = "hidden";
                             }else {
                                 Ext.get(dom).addClass(String(visMode));
                             }
                             Ext.get(dom).setOpacity(1);
                         }
                     });
            }
            return this;
        },
        /**
         * Checks whether the element is currently visible using both visibility and display properties.
         * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
         * @return {Boolean} True if the element is currently visible, else false
         */
        isVisible : function(deep) {
            var vis = !(this.getStyle("visibility") === "hidden" || this.getStyle("display") === "none" || this.hasClass(this.visibilityMode));
            if(deep !== true || !vis){
                return vis;
            }
            var p = this.dom.parentNode;
            while(p && p.tagName.toLowerCase() !== "body"){
                if(!Ext.fly(p, '_isVisible').isVisible()){
                    return false;
                }
                p = p.parentNode;
            }
            return true;
        }
    });

})();
