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

import mx.events.ValidationResultEvent;
/* import mx.managers.ISystemManager;
import mx.managers.SystemManager;
 */
//[ResourceBundle("validators")]

/** 
 *  The RegExpValidator class lets you use a regular expression
 *  to validate a field. 
 *  You pass a regular expression to the validator using the
 *  <code>expression</code> property, and additional flags
 *  to control the regular expression pattern matching 
 *  using the <code>flags</code> property. 
 *
 *  <p>The validation is successful if the validator can find a match
 *  of the regular expression in the field to validate.
 *  A validation error occurs when the validator finds no match.</p>
 *
 *  <p>The RegExpValidator class dispatches the <code>valid</code>
 *  and <code>invalid</code> events.
 *  For an <code>invalid</code> event, the event object is an instance
 *  of the ValidationResultEvent class, and it contains an Array
 *  of ValidationResult objects.</p>
 *
 *  <p>However, for a <code>valid</code> event, the ValidationResultEvent
 *  object contains an Array of RegExpValidationResult objects.
 *  The RegExpValidationResult class is a child class of the
 *  ValidationResult class, and contains additional properties 
 *  used with regular expressions, including the following:</p>
 *  <ul>
 *    <li><code>matchedIndex</code> An integer that contains the starting 
 *      index in the input String of the match.</li>
 *    <li><code>matchedString</code> A String that contains the substring 
 *      of the input String that matches the regular expression.</li>
 *    <li><code>matchedSubStrings</code> An Array of Strings that contains 
 *      parenthesized substring matches, if any. If no substring matches are found, 
 *      this Array is of length 0.  Use matchedSubStrings[0] to access the 
 *      first substring match.</li>
 *  </ul>
 *  
 *  @mxml
 *
 *  <p>The <code>&lt;mx:RegExpValidator&gt;</code> tag 
 *  inherits all of the tag attributes of its superclass,
 *  and adds the following tag attributes:</p>
 *  
 *  <pre>
 *  &lt;mx:RegExpValidator
 *    expression="<i>No default</i>" 
 *    flags="<i>No default</i>" 
 *    noExpressionError="The expression is missing." 
 *    noMatchError="The field is invalid." 
 *  /&gt;
 *  </pre>
 *
 *  @includeExample examples/RegExValidatorExample.mxml
 *  
 *  @see mx.validators.RegExpValidationResult
 *  @see mx.validators.ValidationResult
 *  @see RegExp
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class RegExpValidator extends Validator
{
    //include "../core/Version.as";

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

    /** 
     *  Constructor
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */     
    public function RegExpValidator()
    {
        super();
    }
    
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /** 
     *  @private
     */     
    private var regExp:RegExp;
    
    /** 
     *  @private
     */     
    private var foundMatch:Boolean = false;
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  expression
    //----------------------------------

    /** 
     *  @private
     *  Storage for the expression property.
     */     
    private var _expression:String;
    
    [Inspectable(category="General")]

    /**
     *  The regular expression to use for validation. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get expression():String
    {
        return _expression;
    }
        
    /** 
     *  @private
     */     
    public function set expression(value:String):void
    {
        if (_expression != value)
        {
            _expression = value;

            createRegExp();
        }
    }
    
    //----------------------------------
    //  flags
    //----------------------------------
    
    /** 
     *  @private
     *  Storage for the flags property.
     */     
    private var _flags:String;
    
    [Inspectable(category="General", defaultValue="null")]

    /**
     *  The regular expression flags to use when matching.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function get flags():String
    {
        return _flags;
    }
    
    /** 
     *  @private
     */     
    public function set flags(value:String):void
    {
        if (_flags != value)
        {
            _flags = value;

            createRegExp();
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Properties: Errors
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  noExpressionError
    //----------------------------------

    /**
	 *  @private
	 *  Storage for the noExpressionError property.
	 */
	//private var _noExpressionError:String;
	
    /**
	 *  @private
	 */
	//private var noExpressionErrorOverride:String;
	
    //[Inspectable(category="Errors", defaultValue="null")]

    /** 
     *  Error message when there is no regular expression specifed. 
     *  The default value is "The expression is missing."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	/* public function get noExpressionError():String
	{
		return _noExpressionError;
	} */

	/**
	 *  @private
	 */
	/* public function set noExpressionError(value:String):void
	{
		noExpressionErrorOverride = value;

		_noExpressionError = value != null ?
							 value :
							 resourceManager.getString(
							     "validators", "noExpressionError");
	} */

    //----------------------------------
    //  noMatchError
    //----------------------------------
        
    /**
	 *  @private
	 *  Storage for the noMatchError property.
	 */
	 private var _noMatchError:String;
	 
    /**
	 *  @private
	 */
	/* private var noMatchErrorOverride:String;
	
    [Inspectable(category="Errors", defaultValue="null")]
	*/
    /** 
     *  Error message when there are no matches to the regular expression. 
     *  The default value is "The field is invalid."
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
	public function get noMatchError():String // not implemented
	{
		return _noMatchError;
	}

	/**
	 *  @private
	 */
	public function set noMatchError(value:String):void // not implemented
	{
		//noMatchErrorOverride = value;
//
		//_noMatchError = value != null ?
						//value :
						//resourceManager.getString(
							//"validators", "noMatchError");
	}
    
    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private    
     */
    /* override protected function resourcesChanged():void
    {
		super.resourcesChanged();

        noExpressionError = noExpressionErrorOverride;  
        noMatchError = noMatchErrorOverride;
    } */

    /**
     *  Override of the base class <code>doValidation()</code> method
     *  to validate a regular expression.
     *
     *  <p>You do not call this method directly;
     *  Flex calls it as part of performing a validation.
     *  If you create a custom Validator class, you must implement this method. </p>
     *
     *  @param value Object to validate.
     *
     *  @return For an invalid result, an Array of ValidationResult objects,
     *  with one ValidationResult object for each field examined by the validator. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    /* override protected function doValidation(value:Object):Array
    {
        var results:Array = super.doValidation(value);
        
        // Return if there are errors
        // or if the required property is set to <code>false</code> and length is 0.
        var val:String = value ? String(value) : "";
        if (results.length > 0 || ((val.length == 0) && !required))
            return results;

        return validateRegExpression(value);
    } */
    
    /**
     *  @private
     */
    /* override protected function handleResults(
                                    errorResults:Array):ValidationResultEvent
    {
        var result:ValidationResultEvent;
        
        if (foundMatch)
        {
            result = new ValidationResultEvent(ValidationResultEvent.VALID);
            result.results = errorResults;
        }
        else
        {
            result = super.handleResults(errorResults);
        }
        
        foundMatch = false;    
        
        return result;  
    }
	*/
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private function createRegExp():void
    {
        regExp = new RegExp(_expression,_flags);
    }
    
    /**
     *  @private 
     *  Performs validation on the validator
     */     
    private function validateRegExpression(value:Object):Array
    {
        var results:Array = [];
        foundMatch = false;
    
        if (regExp && _expression != "")
        {
            var result:Object = regExp.exec(String(value));
            if (regExp.global)
            {
                while (result != null) 
                {
                    results.push(new RegExpValidationResult(
                        false, null, "", "", result[0],
                        result.index, result.slice(1)));
                    result = regExp.exec(String(value));
                    foundMatch = true;
                }
            }
            else if (result != null)
            {
                results.push(new RegExpValidationResult(
                    false, null, "", "", result[0],
                    result.index, result.slice(1)));                
                foundMatch = true;
            }   
            
            /*
            if (results.length == 0)
            {
                results.push(new ValidationResult(
                    true, null, "noMatch",
                    noMatchError));
            }
            */
        }
        /*
        else
        {
            results.push(new ValidationResult(
                true, null, "noExpression",
                noExpressionError));
        }
        */
        
        return results;
    }
}

}
