////////////////////////////////////////////////////////////////////////////////
//
//  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.
//
////////////////////////////////////////////////////////////////////////////////

package mx.core
{

import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.IEventDispatcher;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.TimerEvent;
import flash.system.ApplicationDomain;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.utils.Dictionary;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;

import mx.core.RSLItem;
import mx.core.RSLListLoader;
import mx.events.ModuleEvent;
import mx.events.Request;
import mx.events.RSLEvent;
import mx.managers.SystemManagerGlobals;
import mx.resources.IResourceManager;
import mx.resources.ResourceManager;
import mx.utils.LoaderUtil;

use namespace mx_internal;

[ExcludeClass]

/**
 *  @private
 */
public class FlexModuleFactory extends MovieClip
	implements IFlexModuleFactory
{
	include "../core/Version.as";

	//--------------------------------------------------------------------------
	//
	//  Class constants
	//
	//--------------------------------------------------------------------------

    /**
	 *  @private
	 */
    private static const INIT_STATE:int = 0;
    
    /**
	 *  @private
	 */
	private static const RSL_START_LOAD_STATE:int = 1;
    
    /**
	 *  @private
	 */
	private static const APP_LOAD_STATE:int = 2;
    
    /**
	 *  @private
	 */
	private static const APP_START_STATE:int = 3;
    
    /**
	 *  @private
	 */
	private static const APP_RUNNING_STATE:int = 4;
    
    /**
	 *  @private
	 */
	private static const ERROR_STATE:int = 5;

    /**
	 *  @private
	 */
	private static const RSL_LOADING_STATE:int = 6;
    

	//--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------

    /**
	 *  @private
	 */
	public function FlexModuleFactory()
    {
		super();

		mixinList = info()["mixins"];

		stop(); // Make sure to stop the playhead on the currentframe
        
        loaderInfo.addEventListener(Event.INIT, moduleInitHandler);
		loaderInfo.addEventListener(Event.COMPLETE, moduleCompleteHandler);

	    var docFrame:int = totalFrames == 1 ? 0 : 1;

        addEventListener(Event.ENTER_FRAME, docFrameListener);

		timer = new Timer(100);
		timer.addEventListener(TimerEvent.TIMER, timerHandler);
		timer.start();
    }

    private function docFrameListener(event:Event):void
    {
        if (currentFrame == 2)
        {
            removeEventListener(Event.ENTER_FRAME, docFrameListener);
            if (totalFrames > 2)
                addEventListener(Event.ENTER_FRAME, extraFrameListener);
            
            docFrameHandler();
        }
    }
    
    private function extraFrameListener(event:Event):void
    {
        if (lastFrame == currentFrame)
            return;
        
        lastFrame = currentFrame;
        
        if (currentFrame + 1 > totalFrames)
            removeEventListener(Event.ENTER_FRAME, extraFrameListener);
        
        extraFrameHandler();
    }

    //--------------------------------------------------------------------------
	//
	//  Variables
	//
	//--------------------------------------------------------------------------

  	/**
	 *  @private
	 */
	private var rslListLoader:RSLListLoader;
	
    /**
	 *  @private
	 */
	private var mixinList:Array;

    /**
	 *  @private
	 */
    private var state:int = INIT_STATE;
  
    /**
	 *  @private
	 */
	private var appReady:Boolean = false;
    
    /**
     *  @private
     */
    private var appInitDone:Boolean = false;
    
    /**
	 *  @private
	 */
	private var appLoaded:Boolean = false;
    
    /**
	 *  @private
	 */
	private var timer:Timer = null;
    
    /**
     *  @private
     *  Track which frame was last processed
     */
    private var lastFrame:int;
    
    /**
	 *  @private
	 */
	private var nextFrameTimer:Timer = null;
    
    /**
	 *  @private
	 */
	private var errorMessage:String = null;

    /**
     *  @private
     * 
     *  This exists only to provide a reference to this 
     *  module's resource bundles. This module is opting
     *  into referencing its own resource bundles so the
     *  ResourceManager does not need to do it. This 
     *  arrangement keeps the ResourceManager from pinning
     *  the module in memory.
     */
    private var resourceBundles:Array;
    
    /**
     *  @private
     *  Array of RSLData objects that represent the list of RSLs this
     *  module factory is loading. Each element of the Array is an 
     *  Array of RSLData.
     */ 
    private var rslDataList:Array
    
	//--------------------------------------------------------------------------
	//
	//  Properties: IFlexModuleFactory
	//
	//--------------------------------------------------------------------------

    //----------------------------------
    //  allowDomainsInNewRSLs
    //----------------------------------
    
    /**
     *  @private
     */ 
    private var _allowDomainsInNewRSLs:Boolean = true;
    
    /**
     *  @inheritDoc
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion Flex 4.5
     */   
    public function get allowDomainsInNewRSLs():Boolean
    {
        return _allowDomainsInNewRSLs;
    }
    
    /**
     *  @private
     */ 
    public function set allowDomainsInNewRSLs(value:Boolean):void
    {
        _allowDomainsInNewRSLs = value;
    }
    
    //----------------------------------
    //  allowInsecureDomainsInNewRSLs
    //----------------------------------
    
    /**
     *  @private
     */ 
    private var _allowInsecureDomainsInNewRSLs:Boolean = true;
    
    /**
     *  @inheritDoc
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion Flex 4.5
     */   
    public function get allowInsecureDomainsInNewRSLs():Boolean
    {
        return _allowInsecureDomainsInNewRSLs;
    }
    
    /**
     *  @private
     */ 
    public function set allowInsecureDomainsInNewRSLs(value:Boolean):void
    {
        _allowInsecureDomainsInNewRSLs = value;
    }
    
    //----------------------------------
    //  preloadedRSLs
    //----------------------------------
    
    /**
     *  @inheritDoc 
     *  
     */
    public function  get preloadedRSLs():Dictionary
    {
        // Overridden by compiler generate code.
        return null;                
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods: IFlexModuleFactory
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @inheritDoc 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 4.5
     */ 
    public function addPreloadedRSL(loaderInfo:LoaderInfo, rsl:Vector.<RSLData>):void
    {
        preloadedRSLs[loaderInfo] = rsl;
        if (hasEventListener(RSLEvent.RSL_ADD_PRELOADED))
        {
            var rslEvent:RSLEvent = new RSLEvent(RSLEvent.RSL_ADD_PRELOADED);
            rslEvent.loaderInfo = loaderInfo;
            dispatchEvent(rslEvent);
        }
        
    }
    
    /**
   	 *  @private
	 *  This method is overridden in the autogenerated subclass.
	 *  It is part of TLF's ISWFContext interface.
	 *  Although this class does not declare that it implements this interface,
	 *  the autogenerated subclass does.
   	 */
    public function callInContext(fn:Function, thisArg:Object,
								  argArray:Array, returns:Boolean = true):*
    {
        return undefined;
    }

    /**
   	 *  @private
	 *  This method is overridden in the autogenerated subclass.
   	 */
    public function create(... params):Object
    {
	    var mainClassName:String = info()["mainClassName"];
	    
		if (mainClassName == null)
	    {
            var url:String = loaderInfo.loaderURL;
            var dot:Number = url.lastIndexOf(".");
            var slash:Number = url.lastIndexOf("/");
            mainClassName = url.substring(slash + 1, dot);
	    }
	   
        var mainClass:Class = Class(getDefinitionByName(mainClassName));

        return mainClass? new mainClass() : null;
    }

  	/**
   	 *  @private
   	 */
    public function info():Object
    {
        return {};
    }

    /**
     *  Calls Security.allowDomain() for the SWF associated with this FlexModuleFactory.
     *  plus all the SWFs assocatiated with RSLs preloaded by this FlexModuleFactory.
     * 
     */  
    public function allowDomain(... domains):void
    {
        // Overridden by compiler generated code.
    }
    
    /**
     *  Calls Security.allowInsecureDomain() for the SWF associated with this FlexModuleFactory
     *  plus all the SWFs assocatiated with RSLs preloaded by this FlexModuleFactory.
     * 
     */  
    public function allowInsecureDomain(... domains):void
    {
        // Overridden by compiler generated code.
    }
    
    /**
     * @private
     *  A map of fully-qualified interface names,
     *  such as "mx.managers::IPopUpManager",
     *  to instances,
     */
    private var implMap:Object = {};
    
    /**
     * @private
     *  Adds an interface-name-to-implementation-class mapping to the registry,
     *  if a class hasn't already been registered for the specified interface.
     *  The class must implement a getInstance() method which returns
     *  its singleton instance.
     */
    public function registerImplementation(interfaceName:String,
                                           impl:Object):void
    {
        var c:Object = implMap[interfaceName];
        if (!c)
            implMap[interfaceName] = impl;
    }
    
    /**
     * @private
     *  Returns the singleton instance of the implementation class
     *  that was registered for the specified interface,
     *  by looking up the class in the registry
     *  and calling its getInstance() method.
     * 
     *  This method should not be called at static initialization time,
     *  because the factory class may not have called registerImplementation() yet.
     */
    public function getImplementation(interfaceName:String):Object
    {
        var c:Object = implMap[interfaceName];
        return c;
    }
    
    //--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------

   /**
    *  @inheritDoc
    *  
    *  @langversion 3.0
    *  @playerversion Flash 9
    *  @playerversion AIR 1.1
    *  @productversion Flex 3
    */
    public function getDefinitionByName(name:String):Object
    {
       const domain:ApplicationDomain =
		info()["currentDomain"] as ApplicationDomain; 

       var definition:Object;
       if (domain.hasDefinition(name))
          definition = domain.getDefinition(name);

       return definition;
    }

    /**
	 *  @private
	 */
    private function update():void
    {
        switch (state)
        {
            case INIT_STATE:
			{
                if (!appInitDone)
                    return;
                
                getRSLInfo();
                if (rslListLoader.isDone())
                    state = APP_LOAD_STATE;
                else
                    state = RSL_START_LOAD_STATE;
				break;
			}

            case RSL_START_LOAD_STATE:
			{
			    // start loading all the rsls
                rslListLoader.load(null,
                				   rslCompleteHandler,
                				   rslErrorHandler,
                				   rslErrorHandler,
                				   rslErrorHandler);
                state = RSL_LOADING_STATE;
                break;
            }
            case RSL_LOADING_STATE:
            {
                if (rslListLoader.isDone())
                {
                    rslListLoader = null;
                    state = APP_LOAD_STATE;
                }
                break;
			}

            case APP_LOAD_STATE:
			{
                if (appLoaded)
                {
                    deferredNextFrame();
                    state = APP_START_STATE;
                }
                break;
			}

            case APP_START_STATE:
			{
                if (appReady)
                {
            		if (mixinList && mixinList.length > 0)
            		{
            		    var n:int = mixinList.length;
            			for (var i:int = 0; i < n; i++)
            		    {
            		        var c:Class;
            		        try
            		        {
            		           c =	Class(getDefinitionByName(mixinList[i]));
            		           c["init"](this);
            		        }
            		        catch(e:Error)
            		        {
							}
            		    }
                    }

                    state = APP_RUNNING_STATE;
        			timer.removeEventListener(TimerEvent.TIMER, timerHandler);
        			// Stop the timer.
        			timer.reset();

                    dispatchEvent(new Event("ready"));
                    
                    loaderInfo.removeEventListener(Event.COMPLETE, moduleCompleteHandler);
                }
                break;
			}

            case ERROR_STATE:
			{
                if (timer != null)
                {
        			timer.removeEventListener(TimerEvent.TIMER, timerHandler);
        			// stop the timer
        			timer.reset();
                }

                var tf:TextField = new TextField();
                tf.text = errorMessage;
                tf.x = 0;
                tf.y = 0;
                tf.autoSize = TextFieldAutoSize.LEFT;
                addChild(tf);
                
                dispatchEvent(new ModuleEvent(ModuleEvent.ERROR, false, false, 
                              0, 0, errorMessage));
                
                loaderInfo.removeEventListener(Event.COMPLETE, moduleCompleteHandler);
                break;
			}
        }
    }

    /**
     *  @private
     *  Get the RSL URLs and add them to the RSLListLoader.
     */   
    private function getRSLInfo():void
    {
        var rsls:Array = info()["rsls"];
        var cdRsls:Array = info()["cdRsls"];
        
        // Put cross-domain RSL information in the RSL list.
        var rslItemList:Array = [];
        var n:int;
        var i:int;
        if (cdRsls && cdRsls.length > 0)
        {
            rslDataList = LoaderUtil.processRequiredRSLs(this, cdRsls);
            
            var normalizedURL:String = LoaderUtil.normalizeURL(this.loaderInfo);
            var crossDomainRSLItem:Class = Class(getDefinitionByName("mx.core::CrossDomainRSLItem"));
            n = rslDataList.length;
            for (i = 0; i < n; i++)
            {
                var rslWithFailovers:Array = rslDataList[i];
                
                // If crossDomainRSLItem is null, then this is a compiler error. It should not be null.
                var cdNode:Object = new crossDomainRSLItem(rslWithFailovers,
                    normalizedURL,
                    this);
                rslItemList.push(cdNode);               
            }
        }
        
        // Append RSL information in the RSL list.
        if (rsls != null && rsls.length > 0)
        {
            if (normalizedURL == null)
                normalizedURL = LoaderUtil.normalizeURL(this.loaderInfo);
            
            n = rsls.length;
            for (i = 0; i < n; i++)
            {
                var node:RSLItem = new RSLItem(rsls[i].url, 
                                               normalizedURL,
                                               this);
                rslItemList.push(node);
            }
        }
        
        rslListLoader = new RSLListLoader(rslItemList);
    }
    
    /**
	 *  @private
	 */
    public function autorun():Boolean
    {
        return true;
    }

    /**
	 *  @private
	 */
    private function displayError(msg:String):void
    {
        errorMessage = msg;
        state = ERROR_STATE;
        update();
    }
	
    /**
	 *  @private
	 */
	private function docFrameHandler(event:Event = null):void
	{
		// Register singleton classes.
		// Note: getDefinitionByName() will return null
		// if the class can't be found.

		Singleton.registerClass("mx.managers::IBrowserManager",
			Class(getDefinitionByName("mx.managers::BrowserManagerImpl")));

        Singleton.registerClass("mx.managers::ICursorManager",
			Class(getDefinitionByName("mx.managers::CursorManagerImpl")));

        Singleton.registerClass("mx.managers::IDragManager",
			Class(getDefinitionByName("mx.managers::DragManagerImpl")));

        Singleton.registerClass("mx.managers::IHistoryManager",
			Class(getDefinitionByName("mx.managers::HistoryManagerImpl")));

        Singleton.registerClass("mx.managers::ILayoutManager",
			Class(getDefinitionByName("mx.managers::LayoutManager")));

        Singleton.registerClass("mx.managers::IPopUpManager",
			Class(getDefinitionByName("mx.managers::PopUpManagerImpl")));

		Singleton.registerClass("mx.resources::IResourceManager",
			Class(getDefinitionByName("mx.resources::ResourceManagerImpl")));

        Singleton.registerClass("mx.styles::IStyleManager",
			Class(getDefinitionByName("mx.styles::StyleManagerImpl")));

        Singleton.registerClass("mx.styles::IStyleManager2",
			Class(getDefinitionByName("mx.styles::StyleManagerImpl")));

        Singleton.registerClass("mx.managers::IToolTipManager2",
			Class(getDefinitionByName("mx.managers::ToolTipManagerImpl")));

		appReady = true;
        
        // The resources must be installed before update() creates components
		// (such as DateChooswer) that might need them immediately.
		installCompiledResourceBundles();
		
		update();
        
		if (currentFrame < totalFrames)
            deferredNextFrame();
    }
    
    /**
	 *  @private
	 */
	private function installCompiledResourceBundles():void
	{
		//trace("FlexModuleFactory.installCompiledResourceBundles");

		var info:Object = this.info();
		
		var applicationDomain:ApplicationDomain =
            info["currentDomain"];

		var compiledLocales:Array /* of String */ =
			info["compiledLocales"];

		var compiledResourceBundleNames:Array /* of String */ =
			info["compiledResourceBundleNames"];
		
		var resourceManager:IResourceManager =
			ResourceManager.getInstance();
		
		resourceBundles = resourceManager.installCompiledResourceBundles(
			applicationDomain, compiledLocales, compiledResourceBundleNames, true);

		// If the localeChain wasn't specified in the FlashVars of the SWF's
		// HTML wrapper, or in the query parameters of the SWF URL,
		// then initialize it to the list of compiled locales,
        // sorted according to the system's preferred locales as reported by
        // Capabilities.languages or Capabilities.language.
		// For example, if the applications was compiled with, say,
		// -locale=en_US,ja_JP and Capabilities.languages reports [ "ja-JP" ],
        // set the localeChain to [ "ja_JP" "en_US" ].
		if (!resourceManager.localeChain)
			resourceManager.initializeLocaleChain(compiledLocales);
	}

    /**
	 *  @private
	 */
    private function deferredNextFrame():void
    {
        if (currentFrame + 1 <= framesLoaded)
		{
            nextFrame();
		}
        else
        {
            // Next frame isn't baked yet, we'll check back...
    		nextFrameTimer = new Timer(100);
		    nextFrameTimer.addEventListener(TimerEvent.TIMER,
											nextFrameTimerHandler);
		    nextFrameTimer.start();
        }
    }
    /**
	 *  @private
	 */
	private function extraFrameHandler(event:Event = null):void
	{
	    var frameList:Object = info()["frames"];

	    if (frameList && frameList[currentLabel])
	    {
	        var c:Class;
	        try
	        {
	            c = Class(getDefinitionByName(frameList[currentLabel]));
	            c["frame"](this);
	        }
	        catch(e:Error)
	        {
			}
	    }

	    if (currentFrame < totalFrames)
            deferredNextFrame();
	}

	//--------------------------------------------------------------------------
	//
	//  Event handlers
	//
	//--------------------------------------------------------------------------

    /**
	 *  @private
	 */
    private function rslCompleteHandler(event:Event):void
    {
        if (event.target is LoaderInfo)
        {
            var rslIndex:int = rslListLoader.getIndex();
            var rsl:Vector.<RSLData> = Vector.<RSLData>(rslDataList[rslIndex]);
            var moduleFactory:IFlexModuleFactory = this;
            if (rsl && rsl[0].moduleFactory)
                moduleFactory = rsl[0].moduleFactory; 
            
            if (moduleFactory == this)
                preloadedRSLs[event.target] =  rsl;
            else 
                moduleFactory.addPreloadedRSL(LoaderInfo(event.target), rsl);
        }

        update();
    }

    /**
	 *  @private
	 */
    private function rslErrorHandler(event:Event):void
    {
        var rsl:RSLItem = rslListLoader.getItem(rslListLoader.getIndex());
        var detailedError:String;
        var message:String;
        
        if (event is ErrorEvent)
            detailedError = ErrorEvent(event).text;
        
        if (!detailedError)
            detailedError = "";
            
        message = "RSL " + rsl.urlRequest.url + " failed to load. " + detailedError;              
        displayError(message);
    }

    /**
     *  @private
     */
    private function moduleInitHandler(event:Event):void
    {
        loaderInfo.removeEventListener(Event.INIT, moduleInitHandler);
        appInitDone = true;
        update();
    }

    /**
	 *  @private
	 */
    private function moduleCompleteHandler(event:Event):void
    {
        appLoaded = true;
		update();
    }

    /**
	 *  @private
	 */
	private function timerHandler(event:TimerEvent):void
	{
	    if (totalFrames > 2 && framesLoaded >= 2 || 
			framesLoaded == totalFrames)
		{
            appLoaded = true;
		}
		
		update();
    }

    /**
	 *  @private
	 */
	private function nextFrameTimerHandler(event:TimerEvent):void
	{
	    if (currentFrame + 1 <= framesLoaded)
	    {
	        nextFrame();
            nextFrameTimer.removeEventListener(TimerEvent.TIMER,
											   nextFrameTimerHandler);
        	// stop the timer
        	nextFrameTimer.reset();
        }
    }
}

}
