/**
 * @class Ext.air.NativeWindow
 * @extends Ext.air.NativeObservable
 *
 * Wraps the AIR NativeWindow class to give an Ext friendly API.

This class also adds
 * automatic state management (position and size) for the window (by id) and it can be used
 * for easily creating "minimize to system tray" for the main window in your application.


 *
 * Note: Many of the config options for this class can only be applied to NEW windows. Passing
 * in an existing instance of a window along with those config options will have no effect.
 *
 * @constructor
 * @param {Object} config
 */

Ext.air.NativeWindow = function(config){
       
Ext.apply(this, config);
       
       
/**
         * @type String
         */

       
this.id = this.id || Ext.uniqueId();
       
       
this.addEvents(
               
/**
                 * @event close
                 * @param {Object} e The air event object
                 */

               
'close',
               
/**
                 * @event closing
                 * @param {Object} e The air event object
                 */

               
'closing',
               
/**
                 * @event move
                 * @param {Object} e The air event object
                 */

               
'move',
               
/**
                 * @event moving
                 * @param {Object} e The air event object
                 */

               
'moving',
               
/**
                 * @event resize
                 * @param {Object} e The air event object
                 */

               
'resize',
               
/**
                 * @event resizing
                 * @param {Object} e The air event object
                 */

               
'resizing',
               
/**
                 * @event displayStateChange
                 * @param {Object} e The air event object
                 */

               
'displayStateChange',
               
/**
                 * @event displayStateChanging
                 * @param {Object} e The air event object
                 */

               
'displayStateChanging'
       
);
       
       
Ext.air.NativeWindow.superclass.constructor.call(this);
       
       
if(!this.instance){
               
var options = new air.NativeWindowInitOptions();
                options
.systemChrome = this.chrome;
                options
.type = this.type;
                options
.resizable = this.resizable;
                options
.minimizable = this.minimizable;
                options
.maximizable = this.maximizable;
                options
.transparent = this.transparent;
               
               
this.loader = window.runtime.flash.html.HTMLLoader.createRootWindow(false, options, false);
               
this.loader.load(new air.URLRequest(this.file));
       
               
this.instance = this.loader.window.nativeWindow;
       
}else{
               
this.loader = this.instance.stage.getChildAt(0);
       
}
       
       
var provider = Ext.state.Manager;
       
var b = air.Screen.mainScreen.visibleBounds;
       
       
var state = provider.get(this.id) || {};
        provider
.set(this.id, state);
               
       
var win = this.instance;
       
       
var width = Math.max(state.width || this.width, 100);
       
var height = Math.max(state.height || this.height, 100);
       
       
var centerX = b.x + ((b.width/2)-(width/2));
       
var centerY = b.y + ((b.height/2)-(height/2));
       
       
var x = !Ext.isEmpty(state.x, false) ? state.x : (!Ext.isEmpty(this.x, false) ? this.x : centerX);
       
var y = !Ext.isEmpty(state.y, false) ? state.y : (!Ext.isEmpty(this.y, false) ? this.y : centerY);
       
        win
.width = width;
        win
.height = height;
        win
.x = x;
        win
.y = y;
       
        win
.addEventListener('move', function(){
               
if(win.displayState != air.NativeWindowDisplayState.MINIMIZED && win.width > 100 && win.height > 100) {
                        state
.x = win.x;
                        state
.y = win.y;
               
}
       
});    
        win
.addEventListener('resize', function(){
               
if (win.displayState != air.NativeWindowDisplayState.MINIMIZED && win.width > 100 && win.height > 100) {
                        state
.width = win.width;
                        state
.height = win.height;
               
}
       
});
       
       
Ext.air.NativeWindowManager.register(this);
       
this.on('close', this.unregister, this);
       
       
/**
         * @cfg {Boolean} minimizeToTray
         * True to enable minimizing to the system tray. Note: this should only be applied
         * to the primary window in your application. A trayIcon is required.
         */

       
if(this.minimizeToTray){
               
this.initMinimizeToTray(this.trayIcon, this.trayMenu);
       
}
       
};

Ext.extend(Ext.air.NativeWindow, Ext.air.NativeObservable, {
       
       
/**
         * @cfg {air.NativeWindow} instance
         * The native window instance to wrap. If undefined, a new window will be created.
         */

       
       
/**
         * @cfg {String} trayIcon
         * The icon to display when minimized in the system tray
         */

       
/**
         * @cfg {NativeMenu} trayMenu
         * Menu to display when the tray icon is right clicked
         */

       
/**
         * @cfg {String} trayTip
         * Tooltip for the tray icon
         */
   
       
       
/**
         * @cfg {String} chrome
         * The native window chrome (defaults to 'standard', can also be 'none').
         */

        chrome
: 'standard', // can also be none
       
/**
         * @cfg {String} type
         * The native window type - normal, utility or lightweight. (defaults to normal)
         */

        type
: 'normal', // can be normal, utility or lightweight
       
/**
         * @cfg {Number} width
         */

        width
:600,
       
/**
         * @cfg {Number} height
         */

        height
:400,
       
/**
         * @cfg {Boolean} resizable
         */

        resizable
: true,
       
/**
         * @cfg {Boolean} minimizable
         */

        minimizable
: true,
       
/**
         * @cfg {Boolean} maximizable
         */

        maximizable
: true,
       
/**
         * @cfg {Boolean} transparent
         */

        transparent
: false,
       
       
/**
         * Returns the air.NativeWindow instance
         * @return air.NativeWindow
         */

        getNative
: function(){
               
return this.instance;
       
},
       
       
/**
         * Returns the x/y coordinates for centering the windw on the screen
         * @return {x: Number, y: Number}
         */

        getCenterXY
: function(){
               
var b = air.Screen.mainScreen.visibleBounds;
               
return {
                        x
: b.x + ((b.width/2)-(this.width/2)),
                        y
: b.y + ((b.height/2)-(this.height/2))
               
};
       
},
       
       
/**
         * Shows the window
         */

        show
:function(){
               
if(this.trayed){
                       
Ext.air.SystemTray.hideIcon();
                       
this.trayed = false;
               
}
               
this.instance.visible = true;
       
},
       
       
/**
         * Shows and activates the window
         */

        activate
: function(){
               
this.show();
               
this.instance.activate();
       
},
       
       
/**
         * Hides the window
         */

        hide
:function(){
               
this.instance.visible = false;
       
},
       
       
/**
         * Closes the window
         */

        close
: function(){
               
this.instance.close();  
       
},
       
       
/**
         * Returns true if this window is minimized
         * @return Boolean
         */

        isMinimized
:function(){
               
return this.instance.displayState == air.NativeWindowDisplayState.MINIMIZED;
       
},
       
       
/**
         * Returns true if this window is maximized
         * @return Boolean
         */

        isMaximized
:function(){
               
return this.instance.displayState == air.NativeWindowDisplayState.MAXIMIZED;
       
},
       
       
/**
         * Moves the window to the passed xy and y coordinates
         * @param {Number} x
         * @param {Number} y
         */

        moveTo
: function(x, y){
               
this.x = this.instance.x = x;
               
this.y = this.instance.y = y;  
       
},
       
       
/**
         * @param {Number} width
         * @param {Number} height
         */

        resize
: function(width, height){
               
this.width = this.instance.width = width;
               
this.height = this.instance.height = height;    
       
},
       
        unregister
: function(){
               
Ext.air.NativeWindowManager.unregister(this);
       
},
       
        initMinimizeToTray
: function(icon, menu){
               
var tray = Ext.air.SystemTray;
               
                tray
.setIcon(icon, this.trayTip);
               
this.on('displayStateChanging', function(e){
                       
if(e.afterDisplayState == 'minimized'){
                                e
.preventDefault();
                               
this.hide();
                                tray
.showIcon();
                               
this.trayed = true;
                       
}
               
}, this);
               
                tray
.on('click', function(){
                       
this.activate();
               
}, this);
               
               
if(menu){
                        tray
.setMenu(menu);
               
}
       
}
});

/**
 * Returns the first opened window in your application
 * @return air.NativeWindow
 * @static
 */

Ext.air.NativeWindow.getRootWindow = function(){
       
return air.NativeApplication.nativeApplication.openedWindows[0];
};

/**
 * Returns the javascript "window" object of the first opened window in your application
 * @return Window
 * @static
 */

Ext.air.NativeWindow.getRootHtmlWindow = function(){
       
return Ext.air.NativeWindow.getRootWindow().stage.getChildAt(0).window;
};

/**
 * @class Ext.air.NativeWindowGroup
 *
 * A collection of NativeWindows.
 */

Ext.air.NativeWindowGroup = function(){
   
var list = {};

   
return {
               
/**
                 * @param {Object} win
                 */

       
register : function(win){
            list
[win.id] = win;
       
},

       
/**
                 * @param {Object} win
                 */

        unregister
: function(win){
           
delete list[win.id];
       
},

       
/**
                 * @param {String} id
                 */

       
get : function(id){
           
return list[id];
       
},

       
/**
                 * Closes all windows
                 */

        closeAll
: function(){
           
for(var id in list){
               
if(list.hasOwnProperty(id)){
                    list
[id].close();
               
}
           
}
       
},

       
/**
         * Executes the specified function once for every window in the group, passing each
         * window as the only parameter. Returning false from the function will stop the iteration.
         * @param {Function} fn The function to execute for each item
         * @param {Object} scope (optional) The scope in which to execute the function
         */

        each
: function(fn, scope){
           
for(var id in list){
               
if(list.hasOwnProperty(id)){
                   
if(fn.call(scope || list[id], list[id]) === false){
                       
return;
                   
}
               
}
           
}
       
}
   
};
};

/**
 * @class Ext.air.NativeWindowManager
 * @extends Ext.air.NativeWindowGroup
 *
 * Collection of all NativeWindows created.
 *
 * @singleton
 */

Ext.air.NativeWindowManager = new Ext.air.NativeWindowGroup();