Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Collections.Generic
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

''' <summary>
''' Flags for regular expression.
''' </summary>
''' <remarks></remarks>
<Flags(), Serializable()> _
Public Enum RegExModifiers
    None = System.Text.RegularExpressions.RegexOptions.None
    IgnoreCase = System.Text.RegularExpressions.RegexOptions.IgnoreCase
    MultiLine = System.Text.RegularExpressions.RegexOptions.Multiline
End Enum

''' <summary>
''' <para>This is regular expression validator and it it is derive from <see cref="System.Web.UI.WebControls.RegularExpressionValidator" />.</para>
''' <para>The differance is, this validator has two more properties (<see cref="RegExValidator.ValidateEmptyText" /> and <see cref="RegExValidator.ValidationModifiers" />) and uses differant JavaScript to validate on client side.</para>
''' <para>Plus, this also combines required validator.</para>
''' </summary>
''' <remarks>Thnaks to 4GuysFromRolla.</remarks>
Public Class RegExValidator
    Inherits RegularExpressionValidator

    ''' <summary>
    ''' Gets or sets a value indicating whether validator validate the empty text or not..
    ''' </summary>
    ''' <value><c>true</c> if you want to validate the empty text; otherwise, <c>false</c>.</value>
    <Description("Whether validator validates the control when the text of the control is empty.")> _
    <Category("Behavior"), DefaultValue(False)> _
    Public Property ValidateEmptyText() As Boolean
        Get
            Dim o As Object = ViewState("ValidateEmptyText")
            If o Is Nothing Then
                Return False
            Else
                Return CBool(o)
            End If
        End Get
        Set(ByVal value As Boolean)
            ViewState("ValidateEmptyText") = value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the regular expression modifiers.
    ''' </summary>
    ''' <value>The regular expression modifiers.</value>
    <EditorAttribute(GetType(Mitul.FlagEnumUIEditor), GetType(System.Drawing.Design.UITypeEditor))> _
    <Description("Whether the empty string is allowed or not. In other words is it required or not."), Category("Behavior")> _
    Public Property ValidationModifiers() As RegExModifiers
        Get
            Dim o As Object = ViewState("ValidationModifiers")
            If o Is Nothing Then
                Return RegExModifiers.None
            Else
                Return DirectCast(o, RegExModifiers)
            End If
        End Get
        Set(ByVal value As RegExModifiers)
            ViewState("ValidationModifiers") = value
        End Set
    End Property

    Private Function regMods(ByVal p_modifiers As RegExModifiers) As String
        Dim l_retval As String = ""

        If p_modifiers And RegExModifiers.IgnoreCase Then l_retval &= "i"
        If p_modifiers And RegExModifiers.MultiLine Then l_retval &= "m"

        If l_retval.Trim.Length > 0 Then
            Return l_retval
        Else
            Return String.Empty
        End If
    End Function

    Protected Overrides Function EvaluateIsValid() As Boolean
        ' Make sure that the CheckBox is set as directed by MustBeChecked
        Dim l_rgx_mod As System.Text.RegularExpressions.RegexOptions
        Dim l_rgx As System.Text.RegularExpressions.Match
        Dim l_modifiers As RegExModifiers = ValidationModifiers

        l_rgx_mod = RegularExpressions.RegexOptions.None
        If l_modifiers And RegExModifiers.IgnoreCase Then l_rgx_mod = l_rgx_mod Or System.Text.RegularExpressions.RegexOptions.IgnoreCase
        If l_modifiers And RegExModifiers.MultiLine Then l_rgx_mod = l_rgx_mod Or System.Text.RegularExpressions.RegexOptions.Multiline

        l_rgx = System.Text.RegularExpressions.Regex.Match(MyBase.GetControlValidationValue(Me.ControlToValidate), _
                Me.ValidationExpression, l_rgx_mod)

        Return l_rgx.Success
    End Function

    Protected Overrides Sub AddAttributesToRender(ByVal writer As HtmlTextWriter)
        ' Add the client-side code (if needed) 
        If Me.RenderUplevel Then
            ' Use AddAttribute if Helpers.EnableLegacyRendering is true; otherwise, use expando attributes 
            If Helpers.EnableLegacyRendering() Then
                writer.AddAttribute("evaluationfunction", "mitRegExValidatorEvaluateIsValid", False)
                If Not String.IsNullOrEmpty(Me.ValidationExpression) Then writer.AddAttribute("validationexpression", Me.ValidationExpression, False)
                writer.AddAttribute("validateemptytext", IIf(ValidateEmptyText, "true", "false"), False)
                If Me.ValidationModifiers <> RegExModifiers.None Then writer.AddAttribute("validationmodifiers", regMods(Me.ValidationModifiers), False)
            Else
                Me.Page.ClientScript.RegisterExpandoAttribute(Me.ClientID, "evaluationfunction", "mitRegExValidatorEvaluateIsValid", False)
                If Not String.IsNullOrEmpty(Me.ValidationExpression) Then Me.Page.ClientScript.RegisterExpandoAttribute(Me.ClientID, "validationexpression", Me.ValidationExpression, False)
                Me.Page.ClientScript.RegisterExpandoAttribute(Me.ClientID, "validateemptytext", IIf(ValidateEmptyText, "true", "false"), False)
                If Me.ValidationModifiers <> RegExModifiers.None Then Me.Page.ClientScript.RegisterExpandoAttribute(Me.ClientID, "validationmodifiers", regMods(ValidationModifiers), False)
            End If
        End If

        ' We try to do this after we added over attributes because this is the only way I can think of to override
        '   evaluationfunction attribute. It will throw an exception when it will try to add it because we already 
        '   have added. The result is it does eveything else except adding evaluationfunction and validationexpression
        '   attributes which we have added above.
        Try
            MyBase.AddAttributesToRender(writer)
        Catch ex As Exception
        End Try
    End Sub

    Protected Overrides Sub OnPreRender(ByVal e As EventArgs)
        MyBase.OnPreRender(e)

        ' Register the client-side function using WebResource.axd (if needed) 
        ' see: http://aspnet.4guysfromrolla.com/articles/080906-1.aspx 
        If Me.RenderUplevel AndAlso Me.Page IsNot Nothing AndAlso Not Me.Page.ClientScript.IsClientScriptIncludeRegistered(Me.GetType, "skmValidators") Then
            Me.Page.ClientScript.RegisterClientScriptInclude(Me.GetType, "skmValidators", Me.Page.ClientScript.GetWebResourceUrl(Me.GetType, "Mitul.Web.skmValidators.js"))
        End If
    End Sub
End Class
