////////////////////////////////////////////////////////////////////////////////
//
//  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.events.Event;
import flash.events.EventDispatcher;
import flash.system.Capabilities;
import mx.core.IFlexModuleFactory;
import mx.core.mx_internal;
import mx.managers.ISystemManager;
import mx.managers.SystemManagerGlobals;
import mx.styles.CSSDimension;
import mx.styles.CSSOSVersion;
import mx.styles.IStyleManager2;
import mx.styles.StyleManager;

use namespace mx_internal;

[ExcludeClass]

/**
 *  @private
 *  Parser for CSS Media Query syntax.  Not a full-fledged parser.
 *  Doesn't report syntax errors, assumes you have your attributes
 *  and identifiers spelled correctly, etc.
 *  Media query parser now supports os-version selectors such as X, X.Y or X.Y.Z
 *  Note that version with 2 or 3 parts must be  quoted
Examples:
 (os-platform: "ios") AND (min-os-version: 7)
 (os-platform: "android") AND (min-os-version: "4.1.2")

 non standard selectors:
 -flex-device-diagonal
 -flex-min-device-diagonal

 *  
 *  @langversion 3.0
 *  @playerversion Flash 10.2
 *  @playerversion AIR 2.6
 *  @productversion Flex 4.5
 */ 
public class MediaQueryParser  extends EventDispatcher
{
    /**
     *  @private
     *  Table of known media types
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion Flex 4.5
     */
     public static var platformMap:Object =
     {
         AND: "android",
         IOS: "ios",
         MAC: "macintosh",
         WIN: "windows",
         LNX: "linux",
         QNX: "qnx"
     }
    
     /**
      *  @private
      */
     private static var _instance:MediaQueryParser;
     
     /**
      *  Single shared instance of the parser
      * 
      *  @langversion 3.0
      *  @playerversion Flash 10.2
      *  @playerversion AIR 2.6
      *  @productversion Flex 4.5
      */
     public static function get instance():MediaQueryParser
     {
         return _instance;
     }
     
     /**
      *  @private
      */
     public static function set instance(value:MediaQueryParser):void
     {
         if (!_instance)
             _instance = value;
     }
     
     /**
     *  @private
     *  Constructor
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion Flex 4.5
     */
    public function MediaQueryParser(moduleFactory:IFlexModuleFactory = null)
    {        
        applicationDpi = DensityUtil.getRuntimeDPI();
        if (moduleFactory)
        {
            if (moduleFactory.info()["applicationDPI"] != null)
                applicationDpi = moduleFactory.info()["applicationDPI"];
            if (moduleFactory is ISystemManager){
                sm = ISystemManager(moduleFactory);
                if (sm.stage)
                    sm.stage.addEventListener(Event.RESIZE, stage_resizeHandler, false);
            }
        }
        osPlatform = getPlatform();
        osVersion = getOSVersion();
        // compute device  DPI
        deviceDPI = Capabilities.screenDPI;
        // compute width, height and diagonal
        computeDeviceDimensions( );

    }

    /**
     *  Queries that were true
     */
    mx_internal var goodQueries:Object = {};
    
    /**
     *  Queries that were false
     */
    mx_internal var badQueries:Object = {};

    /**
     * system manager for the MQP to compute device dimensions
     */
    private var sm: ISystemManager;

    /** flags are set if device-width / device height are used in any media query.
     * This is an optimization, so that   we know when it's necessary to regenerate styles
     * */
    private var usesDeviceWidth: Boolean = false ;
    private var usesDeviceHeight: Boolean =false;
    private var usesDeviceDiagonal: Boolean = false;
    
    /**
     *  @private
     *  Main entry point.
     * 
     *  @param expression A syntactically correct CSS Media Query
     *  @returns true if valid for this media, false otherwise
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion Flex 4.5
     */
    public function parse(expression:String):Boolean
    {
        // remove whitespace
        expression = StringUtil.trim(expression);
       
        // degenerate expressions
        if (expression == "") return true;
        
        // known queries
        if (goodQueries[expression]) return true;
        if (badQueries[expression]) return false;
                
        // force to lower case cuz case-insensitive
        var originalExpression:String = expression;
        expression = expression.toLowerCase();
        
        //TODO : be smart and do not do a lowercase to do this test
        if (expression == "all") return true;
        
        // get a list of queries.  If any pass then
        // we're good
        var mediaQueries:Array = expression.split(", ");
        var n:int = mediaQueries.length;
        for (var i:int = 0; i < n; i++)
        {
            var result:Boolean;
            var mediaQuery:String = mediaQueries[i];
            var notFlag:Boolean = false;
            // eat only
            if (mediaQuery.indexOf("only ") == 0)
                mediaQuery = mediaQuery.substr(5);
            // remember if this is a "not" expression
            if (mediaQuery.indexOf("not ") == 0)
            {
                notFlag = true;
                mediaQuery = mediaQuery.substr(4);
            }
            // get a list of the parts of the query.
            // it should be media type, optionally
            // followed by "and" followed by
            // optional media feature expressions
            var expressions:Array = tokenizeMediaQuery(mediaQuery);
            var numExpressions:int = expressions.length;
            if (expressions[0] == "all" || expressions[0] == type)
            {
                if (numExpressions == 1 && !notFlag)
                {
                    goodQueries[originalExpression] = true;
                    return true;                                            
                }
                // bail if "and" and no media features (invalid query)
                if (numExpressions == 2) return false;
                // kick off the type and "and"
                expressions.shift();
                expressions.shift();
                // see if the media features match
                result = evalExpressions(expressions);
                // early exit if it returned true;
                if ((result && !notFlag) || (!result && notFlag))
                {
                    goodQueries[originalExpression] = true;
                    return true;                    
                }
            }
            // if we didn't match on media type and we have a notFlag
            // then we match
            else if (notFlag)
            {
                goodQueries[originalExpression] = true;                
                return true;
            }
        }
        badQueries[originalExpression] = true;
        return false;
    }
    
    // break up the expression into pieces
    private function tokenizeMediaQuery(mediaQuery:String):Array
    {        
        var tokens:Array = [];
        // if leading off with "(" then 
        // "all and" is implied
		var pos:int = mediaQuery.indexOf("(");
        if (pos == 0)
        {
            tokens.push("all");
            tokens.push("and");
        }
		else if (pos == -1)
		{
			// no parens means the whole thing should
			// be the media type
			return [ mediaQuery ];
		}
        
        var parenLevel:int = 0;
        var inComment:Boolean = false;
        var n:int = mediaQuery.length;
        var expression:Array = [];
        // walk through each character looking for the pieces
        for (var i:int = 0; i < n; i++)
        {
            var c:String = mediaQuery.charAt(i);
            if (StringUtil.isWhitespace(c) && expression.length == 0)
            {
                // eat extra whitespace between tokens
                continue;
            }
            else
            {
                // this piece should be the media type
                if (c == '/' && i < n - 1 && mediaQuery.charAt(i + 1) == '*')
                {
                    inComment = true;
                    i++;
                    continue;
                }
                if (inComment)
                {
                    if (c == '*' && i < n - 1 && mediaQuery.charAt(i + 1) == '/')
                    {
                        inComment = false;
                        i++;
                    }
                    continue;
                }
                else if (c == "(")  // Not sure whether these should be in the “else” here?
                    parenLevel++;
                else if (c == ")")
                    parenLevel--;
                else
                {
                    expression.push(c);
                }
                
                // If we found whitespace and not in a paren, or just closed a paren,
                // then that's the end of an expression
                if (parenLevel == 0 && (StringUtil.isWhitespace(c) || (c == ")")))
                {
                    if (c != ")")
                        expression.length--;
                    tokens.push(expression.join(""));
                    expression.length = 0; // reset
                }
                
            }
        }
        return tokens;
    }
    
    // take a media feature expression and evaluate it
    private function evalExpressions(expressions:Array):Boolean
    {
        var n:int = expressions.length;
        for (var i:int = 0; i < n; i++)
        {
            var expr:String = expressions[i];
            // skip over "and"
            if (expr == "and")
                continue;
            
            // break into two pieces
            var parts:Array = expr.split(":");
            var key: String = parts[0];
            var min:Boolean = false;
            var max:Boolean = false;
            var flex: Boolean = false;

            // process custom  selectors
            if (key.indexOf("-flex-") == 0){
                 flex =true;
                key = key.substr(6);
            }

            // look for min
            if (key.indexOf("min-") == 0)
            {
                min = true;
                key = key.substr(4);
            }
            // look for max
            else if (key.indexOf("max-") == 0)
            {
                max = true;
                key = key.substr(4);
            }
            // collapse hypens into camelcase ;
            if (key.indexOf("-") > 0)
                key = deHyphenate(key, flex);

            if ( key == "deviceWidth")
                 usesDeviceWidth = true;
            else if (key  =="deviceHeight" )
               usesDeviceHeight = true;
            else if (key == "flexDeviceDiagonal")
                usesDeviceDiagonal = true;

            // if only one part, then it only matters that this property exists
            if (parts.length == 1)
            {
                if (!(key in this))
                    return false;
            }
            // if two parts, then make sure the property exists and value matches
            if (parts.length == 2)
            {
                // if property doesn't exist, then bail
                if (!(key in this))
                    return false;
                var value: Object = normalize(parts[1], this[key]) ;
                var cmp: int = compareValues(this[key], value) ;
                // handle min (we don't check if min is allowed for this property)
                if (min)
                {
                   if (cmp < 0)
                       return false;
                }
                // handle max (we don't check if min is allowed for this property)
                else if (max)
                {
                    if (cmp > 0)
                        return false;
                }
                // bail if the value doesn't match
                else if (cmp != 0)
                {
                    return false;
                }
            }
            
        }
        // all parts matched so return true
        return true;
    }
    
    // strip off  unit if currentValue is Number or int
    //  now supports versions (X.Y.Z) and numbers with units
    private function normalize(s:String, currentValue: Object ):Object
    {
        var index:int;
        
        // strip leading white space
        if (s.charAt(0) == " ")
            s = s.substr(1);
        
        // for the numbers we currently handle, we
        // might find dpi or ppi on it, that we just strip off.
        // We don't handle dpcm yet.
        if (currentValue is Number)
        {
            index = s.indexOf("dpi");
            if (index != -1)
            {
                s = s.substr(0, index);
            }
            return Number(s);
        }
        else if (currentValue is int)
        {
            return int(s);
        }
        // string or CSS value
        // strip quotes of strings
        if (s.indexOf('"') == 0) {
            if (s.lastIndexOf('"') == s.length - 1)
                s = s.substr(1, s.length - 2);
            else
                s = s.substr(1);
        }
        //  string , return
         if (currentValue is String)
        {
             return s;
        }
        else if (currentValue is CSSOSVersion) {
            return new CSSOSVersion(s) ;
        }
        else if (currentValue is CSSDimension) {
              var matches: Array = s.match(/([\d\.]+)(in|cm|dp|pt|px|)$/);    // decimal number following by either units or no unit
             if (matches!= null && matches.length == 3) {
                 var unit: String =  matches[2];
                 var refDPI: Number = unit == CSSDimension.UNIT_DP ? applicationDpi : deviceDPI ; // DPI use applicationDPI  for conversion
                 return new CSSDimension(Number(matches[1]), refDPI,unit );
             }
             else {
                 throw new Error("Unknown unit in css media query:" + s); //TODO NLS Error message
                 return s;
             }

         }
        return s;
    }

    /**  @private
     * Compares current value with test values, using currentValue type to determine comparison function
     *  accepts number, int, string and CSSOSVersion.
     *  Will accept LexicalUnit in the future
     *
     * @param currentValue
     * @param testValue
     * @return   -1 if currentValue < testValue, 1 if currentValue > testValue and 0 if equal
     */
    private function compareValues ( currentValue: Object, testValue: Object): int
    {
        if (currentValue is CSSOSVersion)
           return CSSOSVersion(currentValue).compareTo(CSSOSVersion(testValue))  ;
        else if (currentValue is CSSDimension)
            return CSSDimension(currentValue).compareTo(CSSDimension(testValue));
        else // scalar compare operators
           if ( currentValue == testValue)
              return 0;
           else if ( currentValue < testValue)
             return -1;
           else
             return 1;
    }

    // collapse "-" to camelCase
    private function deHyphenate(s:String, flex: Boolean):String
    {
        var i:int = s.indexOf("-");
        var part: String;
        var c: String;

        while (i > 0)
        {
             part = s.substr(i + 1);
            s = s.substr(0, i);
            c = (part.charAt(0)).toUpperCase();
            s += c + part.substr(1);
            i = s.indexOf("-");
        }
        // if flex, camel case and prefix with flex
        if (flex){
            c = (s.charAt(0)).toUpperCase();
            s = "flex" + c + s.substr(1);
        }
        return s;
    }
    
    private function getPlatform():String
    {
        var s:String = Capabilities.version.substr(0, 3);
        // if there is a friendly name, then use it
        if (platformMap.hasOwnProperty(s))
            return platformMap[s] as String;
        
        // otherwise match against the 3 characters.
        // use lower case because match are case
        // insensitive and we lower case the entire
        // expression
        return s.toLowerCase();
    }

    /** @private
     * returns a CSSOSVersion suitable for MediaQueryParser for the current device operating system version.
     * */
    private function getOSVersion():CSSOSVersion {
		return  new CSSOSVersion(Platform.osVersion) ;
    }

    /** @private recompute device dimension
     *
     * @return true if any dimension that is used in media queries has changed, and styles need to be regenerated
     *   we ignore changes to deviceDiagonal on purpose, so that only changing
     */
    private function computeDeviceDimensions(): Boolean
    {
        if (sm) {
            var w: Number = sm.stage.stageWidth;
            var h: Number = sm.stage.stageHeight;
            var diag: Number = Math.sqrt(w * w + h * h);

           // we need to update styles if device-width is used and has changed or device-height is used and has changed
            // for example after switching orientation or going fullscreen
            // we ignore changes to device diagonal on purpose

            var needToUpdateStyles: Boolean = (usesDeviceWidth && w != deviceWidth.pixelValue)     || (usesDeviceHeight && h != deviceHeight.pixelValue) ;

            deviceWidth = new CSSDimension(w, deviceDPI);
            deviceHeight = new CSSDimension(h, deviceDPI);
            flexDeviceDiagonal = new CSSDimension(  diag, deviceDPI );

           return needToUpdateStyles;
        }
        return false;
    }

    private function stage_resizeHandler(event: Event): void
    {
        if (computeDeviceDimensions())  {
            // reinit query cache then reload styles
            goodQueries = {};
            badQueries = {};
            reinitApplicationStyles();
        }

    }

    private function reinitApplicationStyles( ):void {

        var styleManager: IStyleManager2 = StyleManager.getStyleManager(sm);

        styleManager.stylesRoot = null;
        styleManager.initProtoChainRoots();

        var sms: Array = SystemManagerGlobals.topLevelSystemManagers;
        var n: int = sms.length;
        var i: int;

        // Type as Object to avoid dependency on SystemManager.
        var sm: ISystemManager;
        var cm: Object;

            // Regenerate all the proto chains
            // for all objects in the application.
            for (i = 0; i < n; i++) {
                sm = sms[i];
                cm = sm.getImplementation("mx.managers::ISystemManagerChildManager");
                cm.regenerateStyleCache(true);
            }

        for (i = 0; i < n; i++) {
            sm = sms[i];
            cm = sm.getImplementation("mx.managers::ISystemManagerChildManager");
            cm.notifyStyleChangeInChildren(null, true);      // all styles
        }
    }

    /* real device DPI, use for converting physical units */
    private var deviceDPI: Number ;

    // the type of the media
    public var type:String = "screen";
    
    // the resolution of the media
    public var applicationDpi:Number;
    
    // the platform of the media
    public var osPlatform:String;

    // the platform os version of the media
    public var osVersion: CSSOSVersion;

    /**
     * Physical device width.
     * matches "device-width" selector.
     */
    [Bindable]
    public var deviceWidth: CSSDimension ;

    /**
     * Physical device height.
     * matches "device-height" selector
     */
    [Bindable]
    public var deviceHeight: CSSDimension;

    /**
     *  Physical device diagonal.
     *  matches  "-flex-device-diagonal" selector
     *  prefixed by "-flex" because it's not W3C standard
     *
     */
    public var flexDeviceDiagonal: CSSDimension;

}
}


