/*
 * MoonClock: This control module glues the 'MoonClock' model to the HTML view.
 *
 * Author: John Semler
 */

PACKAGE.Scope('net.jsemler.apps.moonclock', function ($p) {
    
    //
    // Package imports
    //
    var SimpleDialog = $p.Import('windex.SimpleDialog');
    var Dialog = $p.Import('windex.Dialog');
    var Frame = $p.Import('windex.Frame');
    var Menu = $p.Import('windex.Menu');
    var CheckBoxMenuItem = $p.Import('windex.CheckBoxMenuItem');
    var RadioButtonMenuItem = $p.Import('windex.RadioButtonMenuItem');
    var MenuItem = $p.Import('windex.MenuItem');
    var GoogleMap = $p.Import('net.jsemler.libs.googlemap.GoogleMap');
    var Ephemeris = $p.Import('net.jsemler.apps.moonclock.ephemeris.Ephemeris');
    var GLRenderer = $p.Import('net.jsemler.apps.moonclock.graphicspanel.GLRenderer');
    var Preferences = $p.Import('net.jsemler.apps.moonclock.preferences.Preferences');
    var Display = $p.Import('net.jsemler.apps.moonclock.Display');
    var Document = $p.Import('net.jsemler.apps.moonclock.Document');
    var Parameters = $p.Import('net.jsemler.apps.moonclock.Parameters');
    var ZipCodeDialog = $p.Import('net.jsemler.libs.zipcode.ZipCodeDialog');
      
    //
    // MoonClock Class
    //
    
    var MoonClock = $p.Public.Class('MoonClock').Scope(function($c) {
        
        //
        // Private static variables
        //

        var frame, googleMap, simpleDialog, zipCodeDialog, dialogs;
        var glRenderer;

        var zipcodeMenuItem;
        var directionalLightsMenuItem, varyingDiameterMenuItem, showBacksideMenuItem;
        var modelQualityLowMenuItem, modelQualityMediumMenuItem, modelQualityHighMenuItem;
        var imageQualityLowMenuItem, imageQualityMediumMenuItem, imageQualityHighMenuItem;
        var originGeocentricMenuItem, originTopocentricMenuItem;
        var orientationEclipticMenuItem, orientationEquatorMenuItem, orientationHorizonMenuItem;
                
        var parameters = new Parameters().Scope(function($a) {
            var updateTickCounter = 0;
            
            $a.Public.Member('setTickCount', function(tickCount) {
                updateTickCounter = tickCount;
            });
            
            $a.Override.Public.Member('update', function() {    
                
                if (updateTickCounter <= 0) {
                    display.updateDataFields();
                    updateTickCounter = 10;  
                }
                else {
                    updateTickCounter = updateTickCounter - 1;     
                }
                
            });
            
        });
        
        var preferences = new Preferences(parameters);
        var display = new Display(parameters);
        preferences.read();
        
        //
        // Private static functions
        //
        
        var updateMap = function () {
            parameters.setLongitude(GoogleMap.getLongitude());
            parameters.setLatitude(GoogleMap.getLatitude());
        }
                
        function initButtons() {
            var select = $("#moonclock-animation-controls");
            
            var increaseRateButton = $(select).find("div:nth-child(1) > div > button");
            var positiveRateButton = $(select).find("div:nth-child(2) > div > button");
            var pausePlayButton    = $(select).find("div:nth-child(3) > div > button");
            var negativeRateButton = $(select).find("div:nth-child(4) > div > button");
            var decreaseRateButton = $(select).find("div:nth-child(5) > div > button");
            
            $(increaseRateButton).bind("click", function() {
                
                if (parameters.getRate() == -1) {
                    parameters.setRate(1);
                }
                else if (parameters.getRate() >= 1 && parameters.getRate() < 1000000) {
                    parameters.setRate(parameters.getRate()*10);
                }
                
                else if (parameters.getRate() < -1 && parameters.getRate() >= -1000000) {
                    parameters.setRate(parameters.getRate()/10);
                }
                
            });
            
            $(positiveRateButton).bind("click", function() {                
                parameters.setRate(Math.abs(parameters.getRate()));
            });
            
            $(pausePlayButton).bind("click", function() {
                
                if (parameters.isTrackingEnabled()) {
                    parameters.setTrackingEnabled(false);
                    parameters.setTickCount(0);
                    $(pausePlayButton).html('<img src="icons/gtk_media_play_ltr.png"/>');
                }
                else {
                    parameters.setTrackingEnabled(true);
                    parameters.setTickCount(0);
                    $(pausePlayButton).html('<img src="icons/gtk_media_pause.png"/>');
                }
                
            });
            
            $(negativeRateButton).bind("click", function() {                
                parameters.setRate(-Math.abs(parameters.getRate()));
            });
            
            $(decreaseRateButton).bind("click", function() {
                
                if (parameters.getRate() == 1) {
                    parameters.setRate(-1);
                }
                else if (parameters.getRate() > 1 && parameters.getRate() <= 1000000) {
                    parameters.setRate(parameters.getRate()/10);
                }
                
                else if (parameters.getRate() <= -1 && parameters.getRate() > -1000000) {
                    parameters.setRate(parameters.getRate()*10);
                }
                
            });
            
        }

        function initFrame() {
            var menuBar, menu, submenu, menuItem;
            var path = 'PACKAGE.net.jsemler.apps.moonclock.MoonClock.';

            frame = new Frame('moonclock');
            frame.setTitle('Moon Clock');
            frame.setWindowCloseFn(MoonClock.exit);
            menuBar = frame.getMenuBar();

            //
            // Add the 'File' submenus
            //

            menu = new Menu('File');
            menuItem = new MenuItem('Save Cookies');
            menuItem.addActionListener(path + 'saveCookies();');
            menu.add(menuItem);
            menuItem = new MenuItem('Load Cookies');
            menuItem.addActionListener(path + 'loadCookies();');
            menu.add(menuItem);
            menu.addSeparator();
            menuItem = new MenuItem('Exit');
            menuItem.addActionListener(path + 'exit();');
            menu.add(menuItem);
            menuBar.add(menu);

            //
            // Add the 'Settings' submenus
            //

            menu = new Menu('Settings');
            var setTimeMenuItem = menuItem = new MenuItem('Set Time...');
            menuItem.addActionListener(path + 'setTime();');
            menu.add(menuItem);
            menuItem = new MenuItem('Set Time to Now');
            menuItem.addActionListener(path + 'setTimeNow();');
            menu.add(menuItem);
            menuItem = new MenuItem('Set Time to Catalog Start');
            menuItem.addActionListener(path + 'setTimeCatalogStart();');
            menu.add(menuItem);
            menuItem = new MenuItem('Set Time to Catalog End');
            menuItem.addActionListener(path + 'setTimeCatalogEnd();');
            menu.add(menuItem);
            menu.addSeparator();
            zipcodeMenuItem = menuItem = new MenuItem('Set Location using ZipCode...');
            menuItem.addActionListener(path + 'setLocationZipCode();');
            menu.add(menuItem);
            menuItem = new MenuItem('Set Location using Google Map...');
            menuItem.addActionListener(path + 'setLocationGoogleMap();');
            menu.add(menuItem);
            menuBar.add(menu);

            //
            // Add the 'Options' submenus
            //

            menu = new Menu('Options');

            submenu = new Menu('Display');
            directionalLightsMenuItem = menuItem = new CheckBoxMenuItem('Directional Lights');
            menuItem.addActionListener(path + 'toggleDirectionalLights();');
            submenu.add(menuItem);
            varyingDiameterMenuItem = menuItem = new CheckBoxMenuItem('Varying Diameter');
            menuItem.addActionListener(path + 'toggleVaryingDiameter();');
            submenu.add(menuItem);
            showBacksideMenuItem = menuItem = new CheckBoxMenuItem('Show Backside');
            menuItem.addActionListener(path + 'toggleShowBackside();');
            submenu.add(menuItem);
            menu.add(submenu);

            submenu = new Menu('Model Quality');
            modelQualityLowMenuItem = menuItem = new RadioButtonMenuItem('Low');
            menuItem.addActionListener(path + 'setModelQualityLow();');
            submenu.add(menuItem);
            modelQualityMediumMenuItem = menuItem = new RadioButtonMenuItem('Medium');
            menuItem.addActionListener(path + 'setModelQualityMedium();');
            submenu.add(menuItem);
            modelQualityHighMenuItem = menuItem = new RadioButtonMenuItem('High');
            menuItem.addActionListener(path + 'setModelQualityHigh();');
            submenu.add(menuItem);
            menu.add(submenu);

            submenu = new Menu('Image Quality');
            imageQualityLowMenuItem = menuItem = new RadioButtonMenuItem('Low');
            menuItem.addActionListener(path + 'setImageQualityLow();');
            submenu.add(menuItem);
            imageQualityMediumMenuItem = menuItem = new RadioButtonMenuItem('Medium');
            menuItem.addActionListener(path + 'setImageQualityMedium();');
            submenu.add(menuItem);
            imageQualityHighMenuItem = menuItem = new RadioButtonMenuItem('High');
            menuItem.addActionListener(path + 'setImageQualityHigh();');
            submenu.add(menuItem);
            menu.add(submenu);

            submenu = new Menu('Origin');
            originGeocentricMenuItem = menuItem = new RadioButtonMenuItem('Geocentric');
            menuItem.addActionListener(path + 'setOriginGeocentric();');
            submenu.add(menuItem);
            originTopocentricMenuItem = menuItem = new RadioButtonMenuItem('Topocentric');
            menuItem.addActionListener(path + 'setOriginTopocentric();');
            submenu.add(menuItem);
            menu.add(submenu);

            submenu = new Menu('Orientation');
            orientationEclipticMenuItem = menuItem = new RadioButtonMenuItem('Ecliptic');
            menuItem.addActionListener(path + 'setOrientationEcliptic();');
            submenu.add(menuItem);
            orientationEquatorMenuItem = menuItem = new RadioButtonMenuItem('Equator');
            menuItem.addActionListener(path + 'setOrientationEquator();');
            submenu.add(menuItem);
            orientationHorizonMenuItem = menuItem = new RadioButtonMenuItem('Horizon');
            menuItem.addActionListener(path + 'setOrientationHorizon();');
            submenu.add(menuItem);
            menu.add(submenu);

            menuBar.add(menu);

            //
            // Add the 'Help' submenus
            //

            menu = new Menu('Help');
            menuItem = new MenuItem('About...');
            menuItem.addActionListener(path + 'about();');
            menu.add(menuItem);        
            var documentationMenuItem = menuItem = new MenuItem('Documentation...');
            menuItem.addActionListener(path + 'help();');
            menu.add(menuItem);
            menu.addSeparator();
            menuItem = new MenuItem('Model Stats...');
            menuItem.addActionListener(path + 'showModelStats();');
            menu.add(menuItem);
            menuBar.add(menu);

            frame.render();

            setTimeMenuItem.setEnabled(false);
            documentationMenuItem.setEnabled(false);
        }

        function initDialogs() {
            dialogs = {};

            dialogs.help = new Dialog('moonclock-document');
            dialogs.help.setTitle('Moon Clock - Help Document');
            dialogs.help.render();

            dialogs.modelStats = new Dialog('moonclock-model-stats');
            dialogs.modelStats.setTitle('Moon Clock - Model Stats');
            dialogs.modelStats.setResizable(true);
            dialogs.modelStats.setSize(465,625);        
            dialogs.modelStats.render();
        }

        function initSimpleDialog() {
            var aboutMessage;
            $.ajax({
                async: false,
                url: 'about.html',
                success: function(data) {
                    aboutMessage = data;
                }
            });
            simpleDialog = new SimpleDialog('about');
            simpleDialog.setMessage(aboutMessage);
            simpleDialog.setTitle("Moon Clock - About");
            simpleDialog.setType(simpleDialog.INFO);

            simpleDialog.render();
        }

        function initZipCodeDialog() {
            zipCodeDialog = new ZipCodeDialog(parameters, 'moonclock', 'MoonClock');
            zipCodeDialog.render();
        }

        function initGoogleMap() {
            googleMap = new GoogleMap('moonclock-googlemap');
            googleMap.setTitle("Moon Clock Simlulator - Google Map");
            googleMap.setSize(500,500);
            googleMap.setResizable(true);
            googleMap.setUpdateMapFn(updateMap);
            googleMap.render();
        }

        function setEphemerisPreferences() {
                
            switch(parameters.getReferenceOrigin()) {
            default:
            case Ephemeris.referenceOrigin.Geocentric:
                MoonClock.setOriginGeocentric();
                break;

            case Ephemeris.referenceOrigin.Topocentric:
                MoonClock.setOriginTopocentric();
                break;
            }

            switch(parameters.getReferenceFrame()) {
            default:
            case Ephemeris.referenceFrame.Ecliptical:
                MoonClock.setOrientationEcliptic();
                break;

            case Ephemeris.referenceFrame.Equatorial:
                MoonClock.setOrientationEquator();
                break;

            case Ephemeris.referenceFrame.Horizontal:
                MoonClock.setOrientationHorizon();
                break;                    
            }

            GoogleMap.setLongitude(parameters.getLongitude());
            GoogleMap.setLatitude(parameters.getLatitude());                
        }
            
        function setRenderingPreferences() {
                
            switch(parameters.getModelQuality()) {
            default:
            case Parameters.MODEL_QUALITY_LOW:
                MoonClock.setModelQualityLow();
                break;

            case Parameters.MODEL_QUALITY_MEDIUM:
                MoonClock.setModelQualityMedium();
                break;

            case Parameters.MODEL_QUALITY_HIGH:
                MoonClock.setModelQualityHigh();
                break;
            }

            switch(parameters.getImageQuality()) {
            default:
            case Parameters.IMAGE_QUALITY_LOW:
                MoonClock.setImageQualityLow();
                break;

            case Parameters.IMAGE_QUALITY_MEDIUM:
                MoonClock.setImageQualityMedium();
                break;

            case Parameters.IMAGE_QUALITY_HIGH:
                MoonClock.setImageQualityHigh();
                break;
            }
                
        }

        //
        // public static members
        //

        $c.Public.Static.Members({
            
            //
            // File Menu Callbacks
            //

            saveCookies: function() {
                preferences.write();
            },

            loadCookies: function() {
                preferences.read();                
                setEphemerisPreferences();
                setRenderingPreferences();
            },

            exit: function() {
                
                if (history.length > 1) {
                    history.back();
                }
                else {
                    window.close();
                }
            },

            //
            // "Settings" Menu Callbacks
            //

            setTime: function() {},

            setTimeNow: function() {
                var systemTime = new Date().getTime();
                var julianDate = 2440587.5 + (systemTime/1000) /(60*60*24);
                glRenderer.setJulianDate(julianDate);
            },

            setTimeCatalogStart: function() {
                glRenderer.setJulianDate(parameters.getJulianDateStart());
            },

            setTimeCatalogEnd: function() {
                glRenderer.setJulianDate(parameters.getJulianDateEnd());                
            },

            setLocationZipCode: function() {
                zipCodeDialog.show();
            },

            setLocationGoogleMap: function() {
                googleMap.show();
            },

            //
            // "Options...Display" Submenu Callbacks
            //

            toggleDirectionalLights: function() {
                var selected = !directionalLightsMenuItem.isSelected();
                directionalLightsMenuItem.setSelected(selected);
                glRenderer.setDirectionalLights(selected);
                parameters.setDirectionalLights(selected);
            },

            toggleVaryingDiameter: function() {
                var selected = !varyingDiameterMenuItem.isSelected();
                varyingDiameterMenuItem.setSelected(selected);
                glRenderer.setVaryingDiameter(selected);
                parameters.setVaryingDiameter(selected);
            },

            toggleShowBackside: function() {
                var selected = !showBacksideMenuItem.isSelected();
                showBacksideMenuItem.setSelected(selected);
                glRenderer.setShowBackside(selected);
                parameters.setShowBackside(selected);
            },

            setDirectionalLights: function(selected) {
                directionalLightsMenuItem.setSelected(selected);
            },

            setVaryingDiameter: function(selected) {
                varyingDiameterMenuItem.setSelected(selected);
            },

            setShowBackside: function(selected) {
                showBacksideMenuItem.setSelected(selected);
            },

            //
            // "Options...Model Quality" Submenu Callbacks
            //

            setModelQualityLow: function() {
                glRenderer.loadModel('resources/moon_model_i3.bin');
                $.ajax({
                    url: 'resources/moon_model_i3.html',
                    success: function(data) {
                        $('#moonclock-model-stats-content').html(data);
                    }
                });
                modelQualityLowMenuItem.setSelected(true);
                modelQualityMediumMenuItem.setSelected(false);
                modelQualityHighMenuItem.setSelected(false);
                parameters.setModelQuality(Parameters.MODEL_QUALITY_LOW);
            },

            setModelQualityMedium: function() {
                glRenderer.loadModel('resources/moon_model_i4.bin');
                $.ajax({
                    url: 'resources/moon_model_i4.html',
                    success: function(data) {
                        $('#moonclock-model-stats-content').html(data);
                    }
                });
                modelQualityLowMenuItem.setSelected(false);
                modelQualityMediumMenuItem.setSelected(true);
                modelQualityHighMenuItem.setSelected(false);
                parameters.setModelQuality(Parameters.MODEL_QUALITY_MEDIUM);
            },

            setModelQualityHigh: function() {
                glRenderer.loadModel('resources/moon_model_i5.bin');
                $.ajax({
                    url: 'resources/moon_model_i5.html',
                    success: function(data) {
                        $('#moonclock-model-stats-content').html(data);
                    }
                });
                modelQualityLowMenuItem.setSelected(false);
                modelQualityMediumMenuItem.setSelected(false);
                modelQualityHighMenuItem.setSelected(true);
                parameters.setModelQuality(Parameters.MODEL_QUALITY_HIGH);
            },

            //
            // "Options...Image Quality" Submenu Callbacks
            //

            setImageQualityLow: function() {
                glRenderer.loadImage('resources/moon_8k_color_brim16_256x512.jpg');
                imageQualityLowMenuItem.setSelected(true);
                imageQualityMediumMenuItem.setSelected(false);
                imageQualityHighMenuItem.setSelected(false);
                parameters.setImageQuality(Parameters.IMAGE_QUALITY_LOW);
            },

            setImageQualityMedium: function() {
                glRenderer.loadImage('resources/moon_8k_color_brim16_512x1024.jpg');
                imageQualityLowMenuItem.setSelected(false);
                imageQualityMediumMenuItem.setSelected(true);
                imageQualityHighMenuItem.setSelected(false);
                parameters.setImageQuality(Parameters.IMAGE_QUALITY_MEDIUM);
            },

            setImageQualityHigh: function() {
                glRenderer.loadImage('resources/moon_8k_color_brim16_1024x2048.jpg');
                imageQualityLowMenuItem.setSelected(false);
                imageQualityMediumMenuItem.setSelected(false);
                imageQualityHighMenuItem.setSelected(true);
                parameters.setImageQuality(Parameters.IMAGE_QUALITY_HIGH);
            },

            //
            // "Options...Origin" Submenu Callbacks
            //

            setOriginGeocentric: function() {
                if (orientationHorizonMenuItem.isSelected()) {
                    orientationEclipticMenuItem.setSelected(false);
                    orientationEquatorMenuItem.setSelected(true);
                    orientationHorizonMenuItem.setSelected(false);
                    parameters.setReferenceFrame(Ephemeris.referenceFrame.Equatorial);
                }

                zipcodeMenuItem.setEnabled(false);
                orientationHorizonMenuItem.setEnabled(false);            
                originGeocentricMenuItem.setSelected(true);
                originTopocentricMenuItem.setSelected(false);
                parameters.setReferenceOrigin(Ephemeris.referenceOrigin.Geocentric);
                parameters.setTickCount(0);
            },

            setOriginTopocentric: function() {
                zipcodeMenuItem.setEnabled(true);
                orientationHorizonMenuItem.setEnabled(true);
                originGeocentricMenuItem.setSelected(false);
                originTopocentricMenuItem.setSelected(true);
                parameters.setReferenceOrigin(Ephemeris.referenceOrigin.Topocentric);
                parameters.setTickCount(0);
            },

            //
            // "Options...Orientation" Submenu Callbacks
            //

            setOrientationEcliptic: function() {
                orientationEclipticMenuItem.setSelected(true);
                orientationEquatorMenuItem.setSelected(false);
                orientationHorizonMenuItem.setSelected(false);
                parameters.setReferenceFrame(Ephemeris.referenceFrame.Ecliptical);
                parameters.setTickCount(0);
            },

            setOrientationEquator: function() {
                orientationEclipticMenuItem.setSelected(false);
                orientationEquatorMenuItem.setSelected(true);
                orientationHorizonMenuItem.setSelected(false);
                parameters.setReferenceFrame(Ephemeris.referenceFrame.Equatorial);
                parameters.setTickCount(0);
            },

            setOrientationHorizon: function() {
                orientationEclipticMenuItem.setSelected(false);
                orientationEquatorMenuItem.setSelected(false);
                orientationHorizonMenuItem.setSelected(true);
                parameters.setReferenceFrame(Ephemeris.referenceFrame.Horizontal);
                parameters.setTickCount(0);
            },

            //
            // "Help" Menu Callbacks
            //

            about: function() {
                simpleDialog.show();
            },

            help: function() {
                dialogs.help.show();
            },

            showModelStats: function() {
                dialogs.modelStats.show();
            },

            //
            // Initialization
            //
            
            initialize: function() {                
                Document.initialize();
                initButtons();
                initFrame();
                initSimpleDialog();
                initZipCodeDialog();
                initDialogs();
                initGoogleMap();
                setEphemerisPreferences();
                glRenderer = new GLRenderer(parameters);
                glRenderer.start();
                MoonClock.setDirectionalLights(true);
                MoonClock.setVaryingDiameter(true);
                MoonClock.setShowBackside(false);                
                setRenderingPreferences();
            }
            
        });
                
        $c.Public.Static.Member('main', function(args) {
            MoonClock.initialize();
        });
        
    });
    
});