<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                       xmlns:s="library://ns.adobe.com/flex/spark"
                       xmlns:parsley="http://www.spicefactory.org/parsley"
                       title="Apache Flex Developer Tool Suite"
                       width="800" height="550"
                       displayStateChange="displayStateChangeHandler(event)"
                       closing="closingHandler(event)">

    <fx:Declarations>
        <parsley:ContextBuilder>
            <parsley:ViewSettings autowireComponents="true"/>
            <parsley:FlexConfig type="{ApplicationContext}"/>
            <parsley:FlexConfig type="{SettingsContext}"/>
            <parsley:FlexConfig type="{ExecutorContext}"/>
        </parsley:ContextBuilder>
        <parsley:Configure/>
    </fx:Declarations>

    <fx:Metadata>
        [ResourceBundle("Application")]
        [ResourceBundle("SettingsWindow")]
    </fx:Metadata>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <fx:Script><![CDATA[
        import mx.controls.Alert;
        import mx.logging.Log;
        import mx.logging.LogEventLevel;
        import mx.logging.targets.TraceTarget;
        import mx.managers.PopUpManager;

        import org.apache.flex.utilities.developerToolSuite.application.config.SettingsContext;
        import org.apache.flex.utilities.developerToolSuite.executor.application.config.ExecutorContext;
        import org.apache.flex.utilities.developerToolSuite.executor.application.util.LogUtil;
        import org.apache.flex.utilities.developerToolSuite.executor.domain.ISettingsModel;
        import org.apache.flex.utilities.developerToolSuite.executor.infrastructure.message.ApplicationReadyMessage;
        import org.apache.flex.utilities.developerToolSuite.executor.infrastructure.message.InitApplicationMessage;
        import org.apache.flex.utilities.developerToolSuite.infrastructure.event.ModalWindowEvent;
        import org.apache.flex.utilities.developerToolSuite.infrastructure.message.ApplicationExitReadyMessage;
        import org.apache.flex.utilities.developerToolSuite.infrastructure.message.LaunchUIMessage;
        import org.apache.flex.utilities.developerToolSuite.infrastructure.message.RequestExitApplicationMessage;
        import org.apache.flex.utilities.developerToolSuite.presentation.graphic.menu.ApplicationMenu;

        [Inject]
        [Bindable]
        public var applicationMenu:ApplicationMenu;

        [Inject]
        public var applicationSettings:ISettingsModel;

        [MessageDispatcher]
        public var dispatch:Function;

        private var alert:Alert;
        private var appBounds:Rectangle;

        [Init]
        public function init():void {
            addLogTargets();
            LogUtil.getLogger(this).info('Application initialization');

            dispatch(new InitApplicationMessage());

            alert = Alert.show(resourceManager.getString('Application', 'WELCOME_MSG'), resourceManager.getString('Application', 'WELCOME_TITLE'));
        }

        [MessageHandler]
        public function applicationReady(msg:ApplicationReadyMessage):void {

            PopUpManager.removePopUp(alert);
            menu = applicationMenu;

            if (applicationSettings.appBounds) {
                var bounds:Array = applicationSettings.appBounds.split(",");
                appBounds = nativeWindow.bounds = new Rectangle(bounds[0], bounds[1], bounds[2], bounds[3]);
            } else {
                appBounds = nativeWindow.bounds = new Rectangle(120, 120, 1200, 825);
            }

            if (applicationSettings.appDisplayState) {
                (applicationSettings.appDisplayState == NativeWindowDisplayState.MAXIMIZED) ? nativeWindow.maximize() : nativeWindow.restore();
                if (applicationSettings.appDisplayState == NativeWindowDisplayState.NORMAL) {
                    addMoveAndResizeListeners();
                }
            }

            LogUtil.getLogger(this).info('Application ready');

            dispatch(new LaunchUIMessage());
        }

        [MessageHandler(selector='opened')]
        public function modalWindowOpenedHandler(event:ModalWindowEvent):void {
            menu = null;
        }

        [MessageHandler(selector='closed')]
        public function modalWindowClosedHandler(event:ModalWindowEvent):void {
            menu = applicationMenu;
        }

        private function displayStateChangeHandler(event:NativeWindowDisplayStateEvent):void {
            if (event.afterDisplayState == NativeWindowDisplayState.NORMAL) {
                addMoveAndResizeListeners();
            } else {
                removeMoveAndResizeListeners();
            }
        }

        private function addMoveAndResizeListeners():void {
            nativeWindow.addEventListener(NativeWindowBoundsEvent.RESIZE, moveAndResizeHandler);
            nativeWindow.addEventListener(NativeWindowBoundsEvent.MOVE, moveAndResizeHandler);

        }

        private function removeMoveAndResizeListeners():void {
            nativeWindow.removeEventListener(NativeWindowBoundsEvent.RESIZE, moveAndResizeHandler);
            nativeWindow.removeEventListener(NativeWindowBoundsEvent.MOVE, moveAndResizeHandler);

        }

        private function moveAndResizeHandler(event:NativeWindowBoundsEvent):void {
            appBounds = event.afterBounds;
        }

        private function closingHandler(event:Event):void {
            LogUtil.getLogger(this).info('Application Exit requested');
            event.preventDefault();

            var settingsToSave:Object = {};
            settingsToSave.appBounds = appBounds.x + "," + appBounds.y + "," + appBounds.width + "," + appBounds.height;
            settingsToSave.appDisplayState = nativeWindow.displayState;

            dispatch(new RequestExitApplicationMessage(settingsToSave));
        }

        [MessageHandler]
        public function applicationExitReady(msg:ApplicationExitReadyMessage):void {
            LogUtil.getLogger(this).info('Application Exiting');
            this.exit();
        }

        private static function addLogTargets():void {
            var parsleyLogger:TraceTarget = new TraceTarget();
            parsleyLogger.filters = ["org.spicefactory.*", "mx.*"];
            parsleyLogger.level = LogEventLevel.ERROR;
            parsleyLogger.includeCategory = true;
            parsleyLogger.includeLevel = true;
            parsleyLogger.fieldSeparator = " -> ";
            Log.addTarget(parsleyLogger);

            var devLogger:TraceTarget = new TraceTarget();
            devLogger.filters = ["org.apache.flex.utilities.developerToolSuite.*"];
            devLogger.level = LogEventLevel.ALL;
            devLogger.includeCategory = true;
            devLogger.includeLevel = true;
            devLogger.includeTime = true;
            devLogger.fieldSeparator = " -> ";
            Log.addTarget(devLogger);
        }
        ]]></fx:Script>
</s:WindowedApplication>
