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

import flash.display.DisplayObject;
import flash.display.LoaderInfo;
import flash.events.IEventDispatcher;
import flash.system.Capabilities;
import flash.utils.Dictionary;

import mx.core.ApplicationDomainTarget;
import mx.core.IFlexModuleFactory;
import mx.core.mx_internal;
import mx.core.RSLData;
import mx.events.Request;
import mx.managers.SystemManagerGlobals;
import mx.utils.Platform;

import flash.display.Loader;

use namespace mx_internal;

  /**
   *  The LoaderUtil class defines utility methods for use with Flex RSLs and
   *  generic Loader instances.
   *  
   *  @langversion 3.0
   *  @playerversion Flash 9
   *  @playerversion AIR 1.1
   *  @productversion Flex 3
   */
    public class LoaderUtil
    {
        
    include "../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Class variables
    //
    //--------------------------------------------------------------------------

    /**
     *   @private
     * 
     *   An array of search strings and filters. These are used in the normalizeURL
     *   method. normalizeURL is used to remove special Flash Player markup from 
     *   urls, but the array could be appended to by the user to modify urls in other
     *   ways.
     *  
     *   Each object in the array has two fields:
     * 
     *   1. searchString - the string to search the url
     *   2. filterFunction - a function that accepts an url and an index to the first
     *   occurrence of the search string in the url. The function may modify the url
     *   and return a new url. A filterFunction is only called once, for the first
     *   occurrence of where the searchString was found. If there
     *   are multiple strings in the url that need to be processed the filterFunction
     *   should handle all of them on the call. A filter function should 
     *   be defined as follows:
     * 
     *   @param url the url to process.
     *   @param index the index of the first occurrence of the seachString in the url.
     *   @return the new url.
     * 
     *   function filterFunction(url:String, index:int):String
     * 
     */
    mx_internal static var urlFilters:Array = 
            [
                { searchString: "/[[DYNAMIC]]/", filterFunction: dynamicURLFilter}, 
                { searchString: "/[[IMPORT]]/",  filterFunction: importURLFilter}
            ];
    
    //--------------------------------------------------------------------------
    //
    //  Class methods
    //
    //--------------------------------------------------------------------------
        
    /**
     *  The root URL of a cross-domain RSL contains special text 
     *  appended to the end of the URL. 
     *  This method normalizes the URL specified in the specified LoaderInfo instance 
     *  to remove the appended text, if present. 
     *  Classes accessing <code>LoaderInfo.url</code> should call this method 
     *  to normalize the URL before using it.
     *  This method also encodes the url by calling the encodeURI() method
     *  on it. If you want the unencoded url, you must call unencodeURI() on
     *  the results.
     *
     *  @param loaderInfo A LoaderInfo instance.
     *
     *  @return A normalized <code>LoaderInfo.url</code> property.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public static function normalizeURL(loaderInfo:LoaderInfo):String
    {
        var url:String = loaderInfo.url;
        var index:int;
        var searchString:String;
        var urlFilter:Function;
        var n:uint = LoaderUtil.urlFilters.length;
        
        for (var i:uint = 0; i < n; i++)
        {
            searchString = LoaderUtil.urlFilters[i].searchString;
            if ((index = url.indexOf(searchString)) != -1)
            {
                urlFilter = LoaderUtil.urlFilters[i].filterFunction;
                url = urlFilter(url, index);
            }
        }
        
        // On the mac, the player doesn't like filenames with high-ascii
        // characters. Calling encodeURI fixes this problem. We restrict
        // this call to mac-only since it causes problems on Windows.
        if (Platform.isMac)
            return encodeURI(url);
        
        return url;
    }

    /**
     *  @private 
     * 
     *  Use this method when you want to load resources with relative URLs.
     * 
     *  Combine a root url with a possibly relative url to get a absolute url.
     *  Use this method to convert a relative url to an absolute URL that is 
     *  relative to a root URL.
     * 
     *  @param rootURL An url that will form the root of the absolute url.
     *  If the <code>rootURL</code> does not specify a file name it must be 
     *  terminated with a slash. For example, "http://a.com" is incorrect, it
     *  should be terminated with a slash, "http://a.com/". If the rootURL is
     *  taken from loaderInfo, it must be passed thru <code>normalizeURL</code>
     *  before being passed to this function.
     * 
     *  When loading resources relative to an application, the rootURL is 
     *  typically the loaderInfo.url of the application.
     * 
     *  @param url The url of the resource to load (may be relative).
     * 
     *  @return If <code>url</code> is already an absolute URL, then it is 
     *  returned as is. If <code>url</code> is relative, then an absolute URL is
     *  returned where <code>url</code> is relative to <code>rootURL</code>. 
     */ 
    public static function createAbsoluteURL(rootURL:String, url:String):String
    {
        var absoluteURL:String = url;

        // make relative paths relative to the SWF loading it, not the top-level SWF
        if (rootURL &&
            !(url.indexOf(":") > -1 || url.indexOf("/") == 0 || url.indexOf("\\") == 0))
        {
            // First strip off the search string and then any url fragments.
            var index:int;
            
            if ((index = rootURL.indexOf("?")) != -1 )
                rootURL = rootURL.substring(0, index);

            if ((index = rootURL.indexOf("#")) != -1 )
                rootURL = rootURL.substring(0, index);
            
            // If the url starts from the current directory, then just skip
            // over the "./".
            // If the url start from the parent directory, the we need to
            // modify the rootURL.
            var lastIndex:int = Math.max(rootURL.lastIndexOf("\\"), rootURL.lastIndexOf("/"));
            if (url.indexOf("./") == 0)
            {
                url = url.substring(2);
            }
            else
            {
                while (url.indexOf("../") == 0)
                {
                    url = url.substring(3);
                    lastIndex = Math.max(rootURL.lastIndexOf("\\", lastIndex - 1), 
                                                   rootURL.lastIndexOf("/", lastIndex - 1));
                }
            }
                                        
            if (lastIndex != -1)
                absoluteURL = rootURL.substr(0, lastIndex + 1) + url;
        }

        return absoluteURL;
    }
    
    /**
     *  @private
     * 
     *  Takes a list of required rsls and determines:
     *       - which RSLs have not been loaded
     *       - the application domain and IModuleFactory where the
     *         RSL should be loaded
     * 
     *  @param moduleFactory The module factory of the application or module 
     *  to get load information for. If the moduleFactory has not loaded the 
     *  module, then its parent is asked for load information. Each successive
     *  parent is asked until the load information is found or there are no
     *  more parents to ask. Only parents in parent ApplicationDomains are 
     *  searched. Applications in different security domains or sibling
     *  ApplicationDomains do not share RSLs.
     *  
     *  @param rsls An array of RSLs that are required for 
     *  <code>moduleFactory</code>. Each RSL is in an array of RSLData where
     *  the first element is the primary RSL and the remaining elements are 
     *  failover RSLs.
     *  @return Array of RSLData that represents the RSLs to load. RSLs that are
     *  already loaded are not in the listed. 
     */
    mx_internal static function processRequiredRSLs(moduleFactory:IFlexModuleFactory, 
                                                    rsls:Array):Array
    {
        var rslsToLoad:Array = [];  // of Array, where each element is an array 
                                    // of RSLData (primary and failover), return value
        var topLevelModuleFactory:IFlexModuleFactory = SystemManagerGlobals.topLevelSystemManagers[0];
        var currentModuleFactory:IFlexModuleFactory = topLevelModuleFactory;
        var parentModuleFactory:IFlexModuleFactory = null;
        var loaded:Dictionary = new Dictionary();   // contains rsls that are loaded
        var loadedLength:int = 0;
        var resolved:Dictionary = new Dictionary(); // contains rsls that have the app domain resolved
        var resolvedLength:int = 0;
        var moduleFactories:Array = null;
        
        // Start at the top level module factory and work our way down the 
        // module factory chain checking if the any of the rsls are loaded 
        // and resolving application domain targets.
        // We start at the top level module factory because the default rsls
        // will all be loaded here and we won't often have to check other 
        // module factories.
        while (currentModuleFactory != moduleFactory)
        {
            // Need to loop over all the rsls, to see which one are loaded
            // and resolve application domains.
            var n:int = rsls.length;
            for (var i:int = 0; i < n; i++)
            {
                var rsl:Array = rsls[i];

                // Check if the RSL has already been loaded.
                if (!loaded[rsl])
                {
                    if (isRSLLoaded(currentModuleFactory, rsl[0].digest))
                    {
                        loaded[rsl] = 1;
                        loadedLength++;
                        
                        // We may find an rsl loaded in a module factory as we work
                        // our way down the module factory list. If we find one then 
                        // remove it.
                        if (currentModuleFactory != topLevelModuleFactory)
                        {
                            var index:int = rslsToLoad.indexOf(rsl); 
                            if (index != -1)
                                rslsToLoad.splice(index, 1);                        
                        }
                    }
                    else if (rslsToLoad.indexOf(rsl) == -1)
                    {
                        rslsToLoad.push(rsl);   // assume we have to load it
                    }
                } 

                // If the rsl is already loaded or already resolved then
                // skip resolving it.
                if (!loaded[rsl] && resolved[rsl] == null)
                {
                    // Get the parent module factory if we are going to need to 
                    // resolve the application domain target.
                    if (!parentModuleFactory && 
                        RSLData(rsl[0]).applicationDomainTarget == ApplicationDomainTarget.PARENT)
                    {
                        parentModuleFactory = getParentModuleFactory(moduleFactory);           
                    }
                    
                    // Resolve the application domain target.
                    if (resolveApplicationDomainTarget(rsl,
                            moduleFactory,
                            currentModuleFactory,
                            parentModuleFactory,
                            topLevelModuleFactory))
                    {
                        resolved[rsl] = 1;
                        resolvedLength++;                        
                    }
                }
            }
            
            // If process all rsls then get out.
            if (loadedLength + resolvedLength >= rsls.length)
                break;
                
             // If we didn't find everything in the top level module factory then work
            // down towards the rsl's owning module factory. 
            // Build up the module factory parent chain so we can traverse it.
            if (!moduleFactories)
            {
                moduleFactories = [moduleFactory];
                currentModuleFactory = moduleFactory;
                while (currentModuleFactory != topLevelModuleFactory)
                {

                    currentModuleFactory = getParentModuleFactory(currentModuleFactory);
                    
                    // If we couldn't get the parent module factory, then we 
                    // will have to load into the highest application domain
                    // that is available. We won't be able to get a parent 
                    // if a module was loaded without specifying a parent 
                    // module factory.
                    if (!currentModuleFactory)
                        break;
                    
                    if (currentModuleFactory != topLevelModuleFactory)
                        moduleFactories.push(currentModuleFactory);
                    
                    if (!parentModuleFactory)
                        parentModuleFactory = currentModuleFactory;
                }
            }

            currentModuleFactory = moduleFactories.pop();
        }
        
        return rslsToLoad;
    }
    
    /**
     * @private
     * Test whether a url is on the local filesystem. We can only
     * really tell this with URLs that begin with "file:" or a
     * Windows-style drive notation such as "C:". This fails some
     * cases like the "/" notation on Mac/Unix.
     * 
     * @param url
     * the url to check against
     * 
     * @return
     * true if url is local, false if not or unable to determine
     **/
    mx_internal static function isLocal(url:String):Boolean 
    {
        return (url.indexOf("file:") == 0 || url.indexOf(":") == 1);
    }
    
    /**
     * @private
     * Currently (FP 10.x) the ActiveX player (Explorer on Windows) does not
     * handle encoded URIs containing UTF-8 on the local filesystem, but
     * it does handle those same URIs unencoded. The plug-in requires
     * encoded URIs.
     * 
     * @param url
     * url to properly encode, may be fully or partially encoded with encodeURI
     * 
     * @param local
     * true indicates the url is on the local filesystem
     * 
     * @return
     * encoded url that may be loaded with a URLRequest
     **/
    mx_internal static function OSToPlayerURI(url:String, local:Boolean):String 
    {
        
        // First strip off the search string and any url fragments so
        // they will not be decoded/encoded.
        // Next decode the url.
        // Before returning the decoded or encoded string add the search
        // string and url fragment back.
        var searchStringIndex:int;
        var fragmentUrlIndex:int;
        var decoded:String = url;
        
        if ((searchStringIndex = decoded.indexOf("?")) != -1 )
        {
            decoded = decoded.substring(0, searchStringIndex);
        }
        
        if ((fragmentUrlIndex = decoded.indexOf("#")) != -1 )
            decoded = decoded.substring(0, fragmentUrlIndex);
        
        try
        {
            // decode the url
            decoded = decodeURI(decoded);
        }
        catch (e:Error)
        {
            // malformed url, but some are legal on the file system
        }
        
        // create the string to hold the the search string url fragments.
        var extraString:String = null;
        if (searchStringIndex != -1 || fragmentUrlIndex != -1)
        {
            var index:int = searchStringIndex;
            
            if (searchStringIndex == -1 || 
                (fragmentUrlIndex != -1 && fragmentUrlIndex < searchStringIndex))
            {
                index = fragmentUrlIndex;
            }
            
            extraString = url.substr(index);
        }
        
        if (local && flash.system.Capabilities.playerType == "ActiveX")
        {
            if (extraString)
                return decoded + extraString;
            else 
                return decoded;
        }
        
        if (extraString)
            return encodeURI(decoded) + extraString;
        else
            return encodeURI(decoded);            
    }

    /**
     *  @private
     *  Get the parent module factory. 
     * 
     *  @param moduleFactory The module factory to get the parent of.
     * 
     *  @return the parent module factory if available, null otherwise. 
     */
    private static function getParentModuleFactory(moduleFactory:IFlexModuleFactory):IFlexModuleFactory    
    {
        var request:Request = new Request(Request.GET_PARENT_FLEX_MODULE_FACTORY_REQUEST);
        DisplayObject(moduleFactory).dispatchEvent(request); 
        return request.value as IFlexModuleFactory;
    }
    
    /**
     *  @private
     *  Resolve the application domain target. 
     * 
     *  @param rsl to resolve.
     *  @param moduleFactory The module factory loading the RSLs.
     *  @param currentModuleFactory The module factory to search for placeholders.
     *  @param parentModuleFactory The rsl's parent module factory.
     *  @param topLevelModuleFactory The top-level module factory.
     * 
     *  @return true if the application domain target was resolved, 
     *  false otherwise.
     */
    private static function resolveApplicationDomainTarget(rsl:Array, 
                                    moduleFactory:IFlexModuleFactory, 
                                    currentModuleFactory:IFlexModuleFactory, 
                                    parentModuleFactory:IFlexModuleFactory, 
                                    topLevelModuleFactory:IFlexModuleFactory):Boolean 
    {
        var resolvedRSL:Boolean = false;
        var targetModuleFactory:IFlexModuleFactory = null;
        
        var applicationDomainTarget:String = rsl[0].applicationDomainTarget;
        if (isLoadedIntoTopLevelApplicationDomain(moduleFactory))
        {
            targetModuleFactory = topLevelModuleFactory;
        }
        else if (applicationDomainTarget == ApplicationDomainTarget.DEFAULT)
        {
            if (hasPlaceholderRSL(currentModuleFactory, rsl[0].digest))
            {
                targetModuleFactory = currentModuleFactory;
            }
        }
        else if (applicationDomainTarget == ApplicationDomainTarget.TOP_LEVEL)
        {
            targetModuleFactory = topLevelModuleFactory;
        }
        else if (applicationDomainTarget == ApplicationDomainTarget.CURRENT)
        {
            resolvedRSL = true;
        }
        else if (applicationDomainTarget == ApplicationDomainTarget.PARENT)
        {
            // If there is no parent, ignore the target and load into the current
            // app domain. 
            targetModuleFactory = parentModuleFactory;
        }
        else
        {
            resolvedRSL = true; // bogus target, load into current application domain
        }
        
        if (resolvedRSL || targetModuleFactory)
        {
            if (targetModuleFactory)
                updateRSLModuleFactory(rsl, targetModuleFactory);
            return true;
        }
        
        return false;
    }
    
    /**
     *  @private
     *  Determine if the moduleFactory has loaded an rsl that matches the 
     *  specified digest.
     * 
     *  @param moduleFactory The module factory to search.
     *  @param digest The digest to search for.
     *  @return true if a loaded rsl matching the digest was found.
     */
    private static function isRSLLoaded(moduleFactory:IFlexModuleFactory, digest:String):Boolean
    {
        var preloadedRSLs:Dictionary = moduleFactory.preloadedRSLs;
        
        if (preloadedRSLs)
        {
            // loop over the rsls to find a matching digest
            for each (var rsl:Vector.<RSLData> in preloadedRSLs)
            {
                var n:int = rsl.length;
                for (var i:int = 0; i < n; i++)
                {
                    if (rsl[i].digest == digest)
                    {
                        return true;
                    }
                }
            }
        }
        
        return false;
    }
    
    /**
     *  @private
     * 
     *  Determine if the moduleFactory has a placeholder rsl that matches the 
     *  specified digest.
     * 
     *  @param moduleFactory The module factory to search.
     *  @param digest The digest to search for.
     *  @return true if a placeholder rsl matching the digest was found.
     */
    private static function hasPlaceholderRSL(moduleFactory:IFlexModuleFactory, digest:String):Boolean
    {
        var phRSLs:Array = moduleFactory.info()["placeholderRsls"];
        
        if (phRSLs)
        {
            // loop over the rsls to find a matching digest
            var n:int = phRSLs.length;
            for (var i:int = 0; i < n; i++)
            {
                var rsl:Object = phRSLs[i];
                var m:int = rsl.length;
                for (var j:int = 0; j < m; j++)
                {
                    if (rsl[j].digest == digest)
                    {
                        return true;
                    }
                }
            }
        }
        
        return false;
    }
 
    /**
     *  @private
     *  Test if a module factory has been loaded into the top-level application domain.
     * 
     *  @return true if loaded into the top-level application domain, false otherwise.
     */ 
    private static function isLoadedIntoTopLevelApplicationDomain(moduleFactory:IFlexModuleFactory):Boolean
    {
        if (moduleFactory is DisplayObject)
        {
            var displayObject:DisplayObject = DisplayObject(moduleFactory);
            var loaderInfo:LoaderInfo = displayObject.loaderInfo;
            if (loaderInfo && loaderInfo.applicationDomain &&
                loaderInfo.applicationDomain.parentDomain == null)
            {
                return true;
            }
        }
        
        return false;        
    }
    
    /**
     *  @private
     * 
     *  Update the module factory of an rsl, both the primary rsl and all 
     *  failover rsls.
     * 
     *  @param rsl One RSL represented by an array of RSLData. The 
     *  first element in the array is the primary rsl, the others are failovers.
     *  @param moduleFactory  The moduleFactory to set in the primary and 
     *  failover rsls.
     */
    private static function updateRSLModuleFactory(rsl:Array, moduleFactory:IFlexModuleFactory):void
    {
        var n:int = rsl.length;
        for (var i:int = 0; i < n; i++)
        {
            rsl[i].moduleFactory = moduleFactory;
        }
    }
    
    /**
     *  @private
     * 
     *  Strip off the DYNAMIC string(s) appended to the url.
     */
    private static function dynamicURLFilter(url:String, index:int):String
    {
        return url.substring(0, index);
    }

    /**
     *  @private
     * 
     *  Add together the protocol plus everything after "/[[IMPORT]]/".
     */
    private static function importURLFilter(url:String, index:int):String
    {
        var protocolIndex:int = url.indexOf("://");
        return url.substring(0,protocolIndex + 3) + url.substring(index + 12);
    }
    
    }
}