<?xml version="1.0" encoding="utf-8"?>

<!--
     ExpressionView - A package to visualize biclusters
     Copyright (C) 2009 Computational Biology Group, University of Lausanne
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

     This code compiles fine with Flex SDK 3.4.1, SDK 4 is not yet supported.
-->

<mx:Application
    xmlns:mx = "http://www.adobe.com/2006/mxml"
    xmlns:view = "ch.unil.cbg.ExpressionView.view.*"
    layout = "absolute"
    width = "100%" 
    height = "100%"
    scriptTimeLimit = "60" 
    horizontalScrollPolicy="off" 
    verticalScrollPolicy="off" 
    applicationComplete="applicationCompleteHandler()"
    backgroundColor="#d5e5f5" 
    viewSourceURL="srcview/index.html">
    
    <mx:Script>
        <![CDATA[
            import ch.unil.cbg.ExpressionView.events.*;
            import ch.unil.cbg.ExpressionView.model.*;
            import ch.unil.cbg.ExpressionView.styles.*;
            import ch.unil.cbg.ExpressionView.view.*;
            
            import mx.controls.Alert;
            
            CONFIG::air {
                import flash.events.InvokeEvent;
                import flash.desktop.NativeApplication;
                import flash.filesystem.File;
            }
            
            private var menuBar:MenuBar;
            private var backgroundCanvas:BackgroundCanvas;
            private var mainCanvas:MainCanvas;
            private var statusBar:StatusBar;

            private var ged:GeneExpressionData = new GeneExpressionData();
            private var bytes:ByteArray = new ByteArray();
            
            private var oldStageWidth:Number;
            private var oldStageHeight:Number;
            
            private var filename:String;
            private var loader:URLLoader;
            
            CONFIG::air {
                private var file:File;
            }
            
            private function applicationCompleteHandler(): void {
                                
                if ( !menuBar ) {
                    menuBar = new MenuBar;
                    menuBar.setStyle("borderStyle", "solid");
                    menuBar.horizontalScrollPolicy = "off";
                    menuBar.verticalScrollPolicy = "off";
                    addChild(menuBar);
                }
                
                if ( !backgroundCanvas ) {
                    backgroundCanvas = new BackgroundCanvas();
                    backgroundCanvas.horizontalScrollPolicy = "off";
                    backgroundCanvas.verticalScrollPolicy = "off";
                    addChild(backgroundCanvas);

                    if ( !mainCanvas ) {
                        mainCanvas = new MainCanvas();
                        mainCanvas.setStyle("borderStyle", "solid");
                        mainCanvas.horizontalScrollPolicy = "off";
                        mainCanvas.verticalScrollPolicy = "off";
                        mainCanvas.visible = false;
                        backgroundCanvas.addChild(mainCanvas);
                    }

                }

                if ( !statusBar ) {
                    statusBar = new StatusBar();
                    statusBar.setStyle("borderStyle", "solid");
                    statusBar.horizontalScrollPolicy = "off";
                    statusBar.verticalScrollPolicy = "off";
                    addChild(statusBar);
                }

                CONFIG::air {
                    NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, initializeArgumentsHandler);
                }

                addEventListener(MenuEvent.OPEN, processFileHandler);
                ged.addEventListener(GEDCompleteEvent.GEDCOMPLETEEVENT, GEDCompleteHandler);
                ged.addEventListener(UpdateStatusBarEvent.UPDATESTATUSBAREVENT, updateStatusBarHandler);

                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
                stage.addEventListener(Event.RESIZE, resizeHandler);
                stage.addEventListener(MenuEvent.FULLSCREEN, toggleFullScreenHandler);
                
                filename = "";
                if ( Application.application.parameters.filename ) { 
                    filename = Application.application.parameters.filename;
                }

                if ( filename != "" ) {
                    statusBar.visible = true;
                    var request:URLRequest = new URLRequest(filename);
                    loader = new URLLoader();
                    loader.dataFormat = URLLoaderDataFormat.BINARY;
                    loader.addEventListener(ProgressEvent.PROGRESS, fileLoadProgressHandler);
                    loader.addEventListener(Event.COMPLETE, fileLoadCompleteHandler);
                    loader.addEventListener(IOErrorEvent.IO_ERROR, fileLoadErrorHandler);
                    loader.load(request);                    
                }
                            
            }
            
            private function fileLoadProgressHandler(event:ProgressEvent):void {
                var status:String = "loading " + filename + "..." + int(event.bytesLoaded/event.bytesTotal*100) + "% done";
                dispatchEvent(new UpdateStatusBarEvent(status));         
            }

            private function fileLoadCompleteHandler(event:Event):void {
                dispatchEvent(new MenuEvent(MenuEvent.OPEN, [loader.data]));
                loader.removeEventListener(ProgressEvent.PROGRESS, fileLoadProgressHandler);
                dispatchEvent(new UpdateStatusBarEvent(""));                     
                loader.removeEventListener(Event.COMPLETE, fileLoadCompleteHandler);    
            }
            
            private function fileLoadErrorHandler(event:IOErrorEvent):void {
                Alert.show("Unable to load file.", 'Error', mx.controls.Alert.OK);
                loader.removeEventListener(ProgressEvent.PROGRESS, fileLoadProgressHandler);
                loader.removeEventListener(Event.COMPLETE, fileLoadCompleteHandler);
                loader.removeEventListener(IOErrorEvent.IO_ERROR, fileLoadErrorHandler);
            }
            
            CONFIG::air {
                private function fileLoadCompleteHandlerP(event:Event):void {
                    dispatchEvent(new MenuEvent(MenuEvent.OPEN, [file.data]));
                    loader.removeEventListener(ProgressEvent.PROGRESS, fileLoadProgressHandler);
                    dispatchEvent(new UpdateStatusBarEvent(""));                     
                    loader.removeEventListener(Event.COMPLETE, fileLoadCompleteHandlerP);        
                }
            }
            
            override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
                super.updateDisplayList(unscaledWidth, unscaledHeight);

                if ( menuBar ) {
                    menuBar.x = 0;
                    menuBar.y = 0
                    menuBar.percentWidth = 100;
                    menuBar.height = 70;
                }

                if ( backgroundCanvas ) {
                    backgroundCanvas.x = 0;
                    backgroundCanvas.y = 70;
                    backgroundCanvas.percentWidth = 100;
                    backgroundCanvas.height = stage.stageHeight - 90;
                }

                if ( mainCanvas ) {
                    mainCanvas.percentWidth = 100;
                    mainCanvas.percentHeight = 100;
                }
        
                if ( statusBar ) {
                    statusBar.x = 0;
                    statusBar.y = stage.stageHeight - 20;
                    statusBar.percentWidth = 100;
                    statusBar.height = 20;
                }
                                    
            }
                        
            private function resizeHandler(event:Event):void {
                var scalex:Number = stage.stageWidth / oldStageWidth;
                var scaley:Number = (stage.stageHeight - statusBar.height - menuBar.height) / 
                                        (oldStageHeight - statusBar.height - menuBar.height);
                dispatchEvent(new ResizeBrowserEvent(scalex, scaley));
                oldStageWidth = stage.stageWidth;
                oldStageHeight = stage.stageHeight;
            }

            private function toggleFullScreenHandler(event:MenuEvent):void {
                var screen:String = event.data[0];
                if ( screen == "normal" ) {
                    var regExp:RegExp = new RegExp("mac", "i");
                    var match:Boolean = regExp.test(Capabilities.os)
                    if ( match ) {
                        var alert:String = "The fullscreen mode on " + Capabilities.os;
                        alert += " is NOT working properly due to a bug in the Flash Player. ";
                        alert += "Opening files and exporting PDFs is not possible. ";
                    }
                    alert += "Due to security reasons, the fullscreen mode does not allow ";
                    alert += "to enter text or catch keyboard events. All keyboard shortcuts are thus "; 
                    alert += "disabled."; 
                    Alert.show(alert , 'Warning', mx.controls.Alert.OK)
                    oldStageWidth = stage.stageWidth;
                    oldStageHeight = stage.stageHeight;
                    stage.displayState = StageDisplayState.FULL_SCREEN;
                    var scalex:Number = stage.stageWidth / oldStageWidth;
                    var scaley:Number = (stage.stageHeight - statusBar.height - menuBar.height) / 
                                        (oldStageHeight - statusBar.height - menuBar.height);
                    dispatchEvent(new ResizeBrowserEvent(scalex, scaley));
                } else {
                    scalex = stage.stageWidth / oldStageWidth;
                    scaley = (stage.stageHeight - statusBar.height - menuBar.height) / 
                                        (oldStageHeight - statusBar.height - menuBar.height);
                    stage.displayState = StageDisplayState.NORMAL;
                    dispatchEvent(new ResizeBrowserEvent(scalex, scaley));
            
                }
            }

            private function processFileHandler(event:MenuEvent): void {
                statusBar.visible = true;
                bytes = event.data[0];
                bytes.position = 0;
                
                if ( ged.nGenes > 0 ) {
                    Alert.show('Please reload browser window before opening a new file.', 'Error', mx.controls.Alert.OK);
                    return;
                }
                
                dispatchEvent(new UpdateStatusBarEvent("parsing XML"));
                var data:XML = new XML();
                try {
                    data = XML(bytes.readUTFBytes(bytes.length));
                } catch (error:Error) {
                    Alert.show('Malformated XML file:', 'Error', mx.controls.Alert.OK);
                    return;            
                }
                
                try {
                    ged.initialize(data);
                } catch ( error:Error ) {
                    var alert:String;
                    // 20 MB
                    if ( bytes.length > 20000000 ) { 
                        alert = "File is too big for browser applet. ";
                    } else {
                        alert = "Problem loading data in browser applet. ";
                    }
                    alert += "Try stand-alone version of ExpressionView instead."
                    if ( data.child("summary").length() == 0 ) {
                        alert = "Not an ExpressionView file.";
                    }
                    Alert.show(alert, 'Error', mx.controls.Alert.OK);
                    return;                    
                }

            }
            
            private function GEDCompleteHandler(event:GEDCompleteEvent): void {
                mainCanvas.visible = true;
                backgroundCanvas.show = false;
                dispatchEvent(new UpdateGEDataEvent([ged]));
                dispatchEvent(new UpdateStatusBarEvent(""));             
            }

            private function updateStatusBarHandler(event:UpdateStatusBarEvent): void {
                dispatchEvent(new UpdateStatusBarEvent(event.statusbarcontent));             
            }
            
            CONFIG::air {
                private function initializeArgumentsHandler(event:InvokeEvent):void {
                    var args:Array = event.arguments as Array;
                    if ( args.length ) {
                        filename = String(args[0]);
                        statusBar.visible = true;
                        
                        file = new File(filename);
                        file.addEventListener(Event.COMPLETE, fileLoadCompleteHandlerP);
                        file.addEventListener(ProgressEvent.PROGRESS, fileLoadProgressHandler);
                        file.load();

                    }
                }
            }

            
        ]]>
    </mx:Script>

    <mx:Style source="ch/unil/cbg/ExpressionView/styles/global.css"/>
    <mx:Style source="ch/unil/cbg/ExpressionView/styles/tabnavigator.css"/>
    
</mx:Application>