# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
#
# Licensed 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.

import re
from flask import flash, Flask
from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, IntegerField, DecimalField
from wtforms.validators import InputRequired, Optional, NumberRange, ValidationError, StopValidation
#from common.proto.context_pb2 import DeviceOperationalStatusEnum
import ipaddress

def validate_ipv4_address(form, field):             #Custom validator for ensuring a valid IPv4 address is submitted
    # Check for a valid IPv4 address
    # print(field.data)
    try:
        ipaddress.IPv4Address(field.data)
    except ipaddress.AddressValueError:
        raise ValidationError('Invalid IPv4 address format')

def validate_ipv6_address(form, field):             #Custom validator for ensuring a valid IPv6 address is submitted
    # Check for a valid IPv6 address
    try:
        ipaddress.IPv6Address(field.data)
    except ipaddress.AddressValueError:
        raise ValidationError('Invalid IPv6 address format')

def validate_mac_address(form, field):              #Custom validator for ensuring a valid MAC address is submitted 
    # Check for a valid MAC [L2] address
    if not re.match(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$', field.data):
        raise ValidationError('Invalid MAC address format')

def validate_route_distinguisher(form,field):       #Custom validator for the input of Route Distinguisher value
    pattern = r'^([0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]):([0-9]|[1-9][0-9]{1,8}|[1-3][0-9]{9}|4[01][0-9]{8}|42[0-8][0-9]{7}|429[0-3][0-9]{6}|4294[0-8][0-9]{5}|42949[0-5][0-9]{4}|429496[0-6][0-9]{3}|4294967[01][0-9]{2}|42949672[0-8][0-9]|429496729[0-5])$'
    if not re.match(pattern, field.data):
        raise ValidationError('Invalid Route Distinguisher')

def validate_uint32(form, field):                   #Custom validator for ensuring uint32 integers
    if not 0 <= field.data <= 2**32-1:
        raise ValidationError('Value must be a positive integer within the range of uint32')

def validate_NI_as(form, field):                    #Custom validator that checks if NI_protocol_name is BGP and NI_as is not provided
    if form.NI_protocol_name.data == 'BGP' and field.data == None:
        raise StopValidation('AS field is required if the BGP protocol is selected.')

def validator_ADVA(form, field):
    if field.name == 'Device_1_NI_VC_ID' and form.Device_1_IF_vendor.data == 'ADVA' and form.Device_1_NI_VC_ID.data != form.Device_1_IF_vlan_id.data:
        raise StopValidation('For the ADVA vendor, it is mandatory that the VC_ID is the same as the Vlan_ID.')

    if field.name == 'Device_2_NI_VC_ID' and form.Device_2_IF_vendor.data == 'ADVA' and form.Device_2_NI_VC_ID.data != form.Device_2_IF_vlan_id.data:
        raise StopValidation('For the ADVA vendor, it is mandatory that the VC_ID is the same as the Vlan_ID.')


        
class CustomInputRequired():                        #Custom validator that ensures that the required data is provided
    def __init__(self, message=None):                           #Define a constructor that takes an optional message parameter
        self.message = message or "This field is required."     #If message is provided, use it. Otherwise, set a default message.

    def __call__(self, form, field):                            #Define a __call__ method that takes in the form and field to be validated
        if field.data is None or field.data == '':              #Check if the field data is empty or None
            raise StopValidation(self.message)                  #If the data is empty or None, raise a StopValidation exception with the provided message
        
class AddServiceForm_1(FlaskForm):                  #Form-1   -  Formulary Fields -> Select the type of new service to add
    service_type = SelectField('Type of service', choices=[('', 'Select a type of service to add'), ('ACL_L2', 'ACL_L2'), ('ACL_IPV4', 'ACL_IPV4'), ('ACL_IPV6', 'ACL_IPV6'), ('L2VPN', 'L2VPN'), ('L3VPN', 'L3VPN')], validators=[InputRequired()])

class AddServiceForm_ACL_L2(FlaskForm):             #ACL_L2   -  Formulary Fields
    #MANDATORY_PARAMETERS
    name                = StringField('ACL Name', validators=[CustomInputRequired("The name of the ACL is a mandatory parameter")])                                                     #MANDATORY PARAMETER
    type                = SelectField('ACL Type', choices=[('ACL_L2', 'ACL_L2')], validators=[CustomInputRequired("The type of the ACL is a mandatory parameter")])                     #MANDATORY PARAMETER
    sequence_id         = IntegerField('ACL Sequence ID', validators=[CustomInputRequired("The name of the Sequence ID of the ACL is a mandatory parameter"), validate_uint32])         #MANDATORY PARAMETER
    forwarding_action   = SelectField('ACL Fowarding Action', choices=[('', 'Select an action (Mandatory)'), ('ACCEPT', 'Accept'), ('DROP','Drop'),('REJECT','Reject')], validators=[CustomInputRequired("The Forwarding Action of the ACL is a mandatory parameter")])  
    log_action          = SelectField('ACL Log Action', choices=[(None, 'Select a log action (Optional)'), ('LOG_SYSLOG', 'Syslog'), ('LOG_NONE','None')], validators=[Optional()]) 

    #PARAMETERS FOR Associating ACL to IF 
    interface           = StringField('Interface Name', validators=[CustomInputRequired("The name of the Interface is a mandatory parameter")])                                         #MANDATORY PARAMETER
    subinterface        = StringField('Subinterface Index', validators=[Optional()])
    traffic_flow        = SelectField('ACL Traffic Flow Direction', choices=[('', 'Select a direction (Mandatory)'), ('Ingress', 'Ingress'), ('Egress','Egress')], validators=[CustomInputRequired("The direction of the traffic flow is a mandatory parameter")])                                             #MANDATORY PARAMETER

    #SPECIFIC PARAMETERS - Creating ACL Entry [ACL_L2]
    source_mac          = StringField('Source MAC Address', validators=[Optional(), validate_mac_address])  
    destination_mac     = StringField('Destination MAC Address', validators=[Optional(), validate_mac_address]) 

class AddServiceForm_ACL_IPV4(FlaskForm):           #ACL_IPV4 - Formulary Fields
    #MANDATORY_PARAMETERS
    name                = StringField('ACL Name', validators=[CustomInputRequired("The name of the ACL is a mandatory parameter")])                                                     #MANDATORY PARAMETER
    type                = SelectField('ACL Type', choices=[('ACL_IPV4', 'ACL_IPV4')], validators=[CustomInputRequired("The type of the ACL is a mandatory parameter")])                 #MANDATORY PARAMETER
    sequence_id         = IntegerField('ACL Sequence ID', validators=[InputRequired(), NumberRange(min=1, message="Sequence ID must be greater than 0")]) #MANDATORY PARAMETER])                                                                       #MANDATORY PARAMETER
    forwarding_action   = SelectField('ACL Fowarding Action', choices=[(None, 'Select an action (Mandatory)'), ('ACCEPT', 'Accept'), ('DROP','Drop'),('REJECT','Reject')], validators=[InputRequired()])  
    log_action          = SelectField('ACL Log Action', choices=[(None, 'Select a log action (Optional)'), ('LOG_SYSLOG', 'Syslog'), ('LOG_NONE','None')], validators=[Optional()]) 

    #PARAMETERS FOR Associating ACL to IF 
    interface           = StringField('Interface Name', validators=[InputRequired()])                                                                        #MANDATORY PARAMETER
    subinterface        = StringField('Subinterface Index', validators=[Optional()])
    traffic_flow        = SelectField('ACL Traffic Flow Direction', choices=[('', 'Select a direction (Mandatory)'), ('Ingress', 'Ingress'), ('Egress','Egress')], validators=[InputRequired()])                                             #MANDATORY PARAMETER

    #OPTIONAL_PARAMETERS - Creating ACL Entry [ACL_IPV4]
    source_address      = StringField('Source Address', validators=[Optional(), validate_ipv4_address])
    destination_address = StringField('Destination Address', validators=[Optional(), validate_ipv4_address]) 
    protocol            = IntegerField('Protocol',  validators=[Optional(),NumberRange(min=1, max=255, message="Protocol number is between 1 and 255 as defined by IANA")]) #Protocols are defined from 1 - 255 as defined in IANA (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)                             
    hop_limit           = IntegerField('Hop Limit', validators=[Optional(),NumberRange(min=1, max=255, message="The Hop limit value has to be between 0 and 255")])         #Max. value of Hop Limit = 255
    dscp                = IntegerField('DSCP', validators=[Optional(),NumberRange(min=1, max=255, message="The DSCP value has to be between 0 and 63")])                     #Max. value of DSCP = 63
    source_port         = IntegerField('Source Port', validators=[Optional(),NumberRange(min=0, max=65535, message="The Port value has to be between 0 and 655535")])                                       #Range of existing ports in a PC
    destination_port    = IntegerField('Destination Port', validators=[Optional(),NumberRange(min=0, max=65535, message="The Port value has to be between 0 and 655535")])                                  #Range of existing ports in a PC
    tcp_flags           = SelectField('TCP Flags', choices=[(None, 'Select a TCP Flag (Optional)'),('TCP_SYN', 'TCP_SYN'),('TCP_ACK', 'TCP_ACK'),('TCP_RST', 'TCP_RST'),('TCP_FIN', 'TCP_FIN'),('TCP_PSH', 'TCP_PSH'),('TCP_URG', 'TCP_URG') ,('TCP_ECE', 'TCP_ECE'),('TCP_CWR', 'TCP_CWR')], validators=[Optional()]) 

class AddServiceForm_ACL_IPV6(FlaskForm):           #ACL_IPV6 - Formulary Fields
    #MANDATORY_PARAMETERS
    name                = StringField('ACL Name', validators=[InputRequired()])                                                                           #MANDATORY PARAMETER
    type                = SelectField('ACL Type', choices=[('ACL_IPV6', 'ACL_IPV6')], validators=[InputRequired()])                                           #MANDATORY PARAMETER
    sequence_id         = IntegerField('ACL Sequence ID', validators=[InputRequired(), NumberRange(min=1, message="Sequence ID must be greater than 0")]) #MANDATORY PARAMETER])                                                                       #MANDATORY PARAMETER
    forwarding_action   = SelectField('ACL Fowarding Action', choices=[(None, 'Select an action (Mandatory)'), ('ACCEPT', 'Accept'), ('DROP','Drop'),('REJECT','Reject')], validators=[InputRequired()])  
    log_action          = SelectField('ACL Log Action', choices=[(None, 'Select a log action (Optional)'), ('LOG_SYSLOG', 'Syslog'), ('LOG_NONE','None')], validators=[Optional()]) 

    #PARAMETERS FOR Associating ACL to IF 
    interface           = StringField('Interface Name', validators=[InputRequired()])                                                                        #MANDATORY PARAMETER
    subinterface        = StringField('Subinterface Index', validators=[Optional()])
    traffic_flow        = SelectField('ACL Traffic Flow Direction', choices=[('', 'Select a direction (Mandatory)'), ('Ingress', 'Ingress'), ('Egress','Egress')], validators=[InputRequired()])                                             #MANDATORY PARAMETER

    #SPECIFIC PARAMETERS - Creating ACL Entry [ACL_IPV6]
    source_address      = StringField('Source Address', validators=[Optional(), validate_ipv6_address])
    destination_address = StringField('Destination Address', validators=[Optional(), validate_ipv6_address])
    protocol            = IntegerField('Protocol',  validators=[Optional(),NumberRange(min=1, max=255, message="Protocol number is between 1 and 255 as defined by IANA")]) #Protocols are defined from 1 - 255 as defined in IANA (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml)                             
    hop_limit           = IntegerField('Hop Limit', validators=[Optional(),NumberRange(min=1, max=255, message="The Hop limit value has to be between 0 and 255")])         #Max. value of Hop Limit = 255
    dscp                = IntegerField('DSCP', validators=[Optional(),NumberRange(min=1, max=255, message="The DSCP value has to be between 0 and 63")])                     #Max. value of DSCP = 63

class AddServiceForm_L2VPN(FlaskForm):              #L2VPN    - Formulary Fields
    #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY)
    service_name       = StringField('Service Name', validators=[CustomInputRequired()])                                                                    #MANDATORY PARAMETER
    service_type       = SelectField('Service Type', choices=[(2, '2 (L2NM)')], validators=[CustomInputRequired()])                                         #MANDATORY PARAMETER - FIXED VALUE -> L2NM
    service_device_1   = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()])                         #MANDATORY PARAMETER - DEVICE-1
    service_device_2   = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()])                         #MANDATORY PARAMETER - DEVICE-2
    service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()])                                                               #MANDATORY PARAMETER - DEVICE-1
    service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()])                                                               #MANDATORY PARAMETER - DEVICE-2
    #Device_1_IF_vendor = SelectField ('Device_1 Vendor', choices=[('', 'Select a vendor (Mandatory)'),('ADVA', 'ADVA'), ('CISCO','CISCO'), ('Huawei', 'Huawei'),('Juniper', 'Juniper'),('Nokia', 'Nokia')], validators=[CustomInputRequired()])  #MANDATORY PARAMETER - DEVICE-1
    #Device_2_IF_vendor = SelectField ('Device_2 Vendor', choices=[('', 'Select a vendor (Mandatory)'),('ADVA', 'ADVA'), ('CISCO','CISCO'), ('Huawei', 'Huawei'),('Juniper', 'Juniper'),('Nokia', 'Nokia')], validators=[CustomInputRequired()])  #MANDATORY PARAMETER - DEVICE-2   
    #Device_1_Template  = SelectField ('Device_1 Template', choices=[('', 'Select a type of template (Mandatory)'),('Jinja', 'Jinja'), ('Pyangbind','Pyangbind')], validators=[CustomInputRequired()])  #MANDATORY PARAMETER - DEVICE-1
    #Device_2_Template  = SelectField ('Device_2 Template', choices=[('', 'Select a type of template (Mandatory)'),('Jinja', 'Jinja'), ('Pyangbind','Pyangbind')], validators=[CustomInputRequired()])  #MANDATORY PARAMETER - DEVICE-2   
   

    #GENERIC SERVICE CONSTRAINT PARAMETERS (ALL OPTIONAL)
    service_capacity    = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)])                            #OPTIONAL PARAMETER
    service_latency     = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)])                             #OPTIONAL PARAMETER
    service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)])                                       #OPTIONAL PARAMETER
    service_isolation   = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()])
    
    #NI parameters
    #Common for the service
    NI_name                      = StringField('NI Name', validators=[CustomInputRequired()])                                                                   #MANDATORY PARAMETER
    #NI_type                      = SelectField('NI Type', choices=[('L2VSI', 'L2VSI')], validators=[CustomInputRequired()])                                     #MANDATORY PARAMETER - FIXED VALUE -> L2VSI
    NI_mtu                       = IntegerField('NI MTU', default=1500, validators=[CustomInputRequired(), NumberRange(min=0, message="MTU value can't be negative")]) #MANDATORY PARAMETER - FIXED VALUE -> 1500
    NI_description               = StringField('NI Description', validators=[Optional()])                                                                       #OPTIONAL  PARAMETER
    #Device_1 specific
    #Device_1_NI_VC_ID            = IntegerField('Device_1 NI VC_ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative"), validator_ADVA])    #MANDATORY  PARAMETER
    Device_1_NI_VC_ID            = IntegerField('Device_1 NI VC_ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative")])    #MANDATORY  PARAMETER
    Device_1_NI_remote_system    = StringField('Device_1 NI remote_system', validators=[CustomInputRequired(),validate_ipv4_address])                           #MANDATORY  PARAMETER
    Device_1_NI_connection_point = StringField('Device_1 NI conn_point', validators=[CustomInputRequired()])                                                    #MANDATORY  PARAMETER
    #Device_2 specific
    #Device_2_NI_VC_ID            = IntegerField('Device_2 NI VC_ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative"), validator_ADVA])    #MANDATORY  PARAMETER
    Device_2_NI_VC_ID            = IntegerField('Device_2 NI VC_ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative")])    #MANDATORY  PARAMETER
    Device_2_NI_remote_system    = StringField ('Device_2 NI remote_system', validators=[CustomInputRequired(),validate_ipv4_address])                          #MANDATORY  PARAMETER
    Device_2_NI_connection_point = StringField ('Device_2 NI conn_point', validators=[CustomInputRequired()])                                                   #MANDATORY  PARAMETER
     
    #Interface parameters (DEVICE SPECIFIC)
    #Device-1
    #Device_1_IF_name        = StringField ('Device_1 Interface Name', validators=[CustomInputRequired()])                                                               #MANDATORY PARAMETER
    #Device_1_IF_type        = StringField ('Device_1 Interface Type', default="l2vlan", validators=[CustomInputRequired()])                                             #MANDATORY PARAMETER - FIXED VALUE -> l2vlan?
    Device_1_IF_index       = IntegerField('Device_1 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")])     #MANDATORY PARAMETER
    Device_1_IF_vlan_id     = IntegerField('Device_1 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")])              #MANDATORY PARAMETER 
    Device_1_IF_mtu         = IntegerField('Device_1 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")])                #OPTIONAL  PARAMETER - FIXED VALUE -> 3000?
    Device_1_IF_description = StringField ('Device_1 SubIF Description', validators=[Optional()])                                                                       #OPTIONAL  PARAMETER   
    #Device-2
    #Device_2_IF_name        = StringField ('Device_2 Interface Name', validators=[CustomInputRequired()])                                                               #MANDATORY PARAMETER
    #Device_2_IF_type        = StringField ('Device_2 Interface Type', default="l2vlan", validators=[CustomInputRequired()])                                             #MANDATORY PARAMETER - FIXED VALUE -> l2vlan?
    Device_2_IF_index       = IntegerField('Device_2 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")])     #MANDATORY PARAMETER
    Device_2_IF_vlan_id     = IntegerField('Device_2 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")])              #MANDATORY PARAMETER 
    Device_2_IF_mtu         = IntegerField('Device_2 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")])                #OPTIONAL  PARAMETER - FIXED VALUE -> 3000?
    Device_2_IF_description = StringField ('Device_2 SubIF Description', validators=[Optional()])                                                                       #OPTIONAL  PARAMETER                                                                                              

class AddServiceForm_L3VPN(FlaskForm):              #L3VPN    - Formulary Fields 
    #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY)
    service_name     = StringField('Service Name', validators=[CustomInputRequired()])                                                          #MANDATORY PARAMETER
    service_type     = SelectField('Service Type', choices=[(1, '1 (L3NM)')], validators=[CustomInputRequired()])                               #MANDATORY PARAMETER - FIXED VALUE -> L2NM
    service_device_1   = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()])             #MANDATORY PARAMETER - DEVICE-1
    service_device_2   = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()])             #MANDATORY PARAMETER - DEVICE-2
    service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()])                                                   #MANDATORY PARAMETER - DEVICE-1
    service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()])                                                   #MANDATORY PARAMETER - DEVICE-2
    #Device_1_IF_vendor = SelectField ('Device_1 Vendor', choices=[('', 'Select a vendor (Mandatory)'),('ADVA', 'ADVA'), ('CISCO','CISCO'), ('Huawei', 'Huawei'),('Juniper', 'Juniper'),('Nokia', 'Nokia')], validators=[CustomInputRequired()])  #MANDATORY PARAMETER    
    #Device_2_IF_vendor = SelectField ('Device_2 Vendor', choices=[('', 'Select a vendor (Mandatory)'),('ADVA', 'ADVA'), ('CISCO','CISCO'), ('Huawei', 'Huawei'),('Juniper', 'Juniper'),('Nokia', 'Nokia')], validators=[CustomInputRequired()])  #MANDATORY PARAMETER    
    #Device_1_Template  = SelectField ('Device_1 Template', choices=[('', 'Select a type of template (Mandatory)'),('Jinja', 'Jinja'), ('Pyangbind','Pyangbind')], validators=[CustomInputRequired()])  #MANDATORY PARAMETER - DEVICE-1
    #Device_2_Template  = SelectField ('Device_2 Template', choices=[('', 'Select a type of template (Mandatory)'),('Jinja', 'Jinja'), ('Pyangbind','Pyangbind')], validators=[CustomInputRequired()])  #MANDATORY PARAMETER - DEVICE-2   
   
    #GENERIC SERVICE CONSTRAINT PARAMETERS (ALL OPTIONAL)
    service_capacity    = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)])                #OPTIONAL PARAMETER
    service_latency     = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)])                 #OPTIONAL PARAMETER
    service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)])                           #OPTIONAL PARAMETER
    service_isolation   = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()])
     
    ##  Network Instance (NI) PARAMS   
    #Create a NI
    NI_name           = StringField('Name', validators=[InputRequired()])                                                                       #MANDATORY PARAMETER
    #NI_type           = SelectField('Type', choices=[('L3VRF', 'L3VRF')], validators=[InputRequired()])                                         #MANDATORY PARAMETER - FIXED VALUE -> L3VRF
    NI_route_distinguisher = StringField('Route Distinguisher', validators=[InputRequired(),validate_route_distinguisher])                      #MANDATORY PARAMETER                  
    NI_router_id      = StringField('Router ID', validators=[Optional(), validate_ipv4_address])                                                #OPTIONAL  PARAMETER                  
    NI_description    = StringField('Description', validators=[Optional()])                                                                     #OPTIONAL  PARAMETER
    #Add a protocol to NI
    NI_protocol       = SelectField('Protocol', choices=[('', 'Select a type (Mandatory)'),('STATIC', 'STATIC'),('DIRECTLY_CONNECTED', 'DIRECTLY_CONNECTED'),('BGP', 'BGP')], validators=[InputRequired()])  
    NI_as             = IntegerField('AS', default=None, validators=[validate_NI_as, Optional(), validate_uint32])                      
    #Create Connections Table
    #NI_src_protocol   = SelectField('Source Protocol', choices=[('', 'Select a type'),('STATIC', 'STATIC'),('DIRECTLY_CONNECTED', 'DIRECTLY_CONNECTED'),('BGP', 'BGP')], validators=[InputRequired()])                                                    
    #NI_dst_protocol   = SelectField('Destination Protocol', choices=[('', 'Select a type'),('STATIC', 'STATIC'),('DIRECTLY_CONNECTED', 'DIRECTLY_CONNECTED'),('BGP', 'BGP')], validators=[InputRequired()])                                                          
    NI_address_family = SelectField('Protocol Address Family', choices=[('', 'Select a type (Mandatory)'),('IPV4', 'IPV4'),('IPV6', 'IPV6')], validators=[InputRequired()])        
    NI_default_import_policy = SelectField('Default Network Instance Import Policy', choices=[('', 'Select a policy (Mandatory)'),('ACCEPT_ROUTE', 'ACCEPT_ROUTE'),('REJECT_ROUTE', 'REJECT_ROUTE')], validators=[Optional()])                                 
    #Associate RP to NI
    NI_import_policy  = StringField('Name of the Network Instance Import Policy', validators=[Optional()])                                      #OPTIONAL  PARAMETER                                
    NI_export_policy  = StringField('Name of the Network Instance Export Policy', validators=[Optional()])                                      #OPTIONAL  PARAMETER

    ## Interface (IF) PARAMS
    #Device-1
    #Device_1_IF_name        = StringField ('Device_1 Interface Name', validators=[CustomInputRequired()])                                                               #MANDATORY PARAMETER
    #Device_1_IF_type        = StringField ('Device_1 Interface Type', default="l3ipvlan", validators=[CustomInputRequired()])                                           #MANDATORY PARAMETER - FIXED VALUE -> l3ipvlan?
    Device_1_IF_index       = IntegerField('Device_1 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")])     #MANDATORY PARAMETER
    Device_1_IF_vlan_id     = IntegerField('Device_1 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")])              #MANDATORY PARAMETER 
    Device_1_IF_mtu         = IntegerField('Device_1 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")])                #OPTIONAL  PARAMETER - FIXED VALUE -> 3000?
    Device_1_IF_address_ip  = StringField('Device_1 IP Address', validators=[CustomInputRequired(), validate_ipv4_address])                                             #MANDATORY PARAMETER                                                    
    Device_1_IF_address_prefix = IntegerField('Device_1 IP Prefix length', validators=[CustomInputRequired(), validate_uint32])                                         #MANDATORY PARAMETER       
    Device_1_IF_description = StringField ('Device_1 SubIF Description', validators=[Optional()])                                                                       #OPTIONAL  PARAMETER   
    #Device-2
    #Device_2_IF_name        = StringField ('Device_2 Interface Name', validators=[CustomInputRequired()])                                                               #MANDATORY PARAMETER
    #Device_2_IF_type        = StringField ('Device_1 Interface Type', default="l3ipvlan", validators=[CustomInputRequired()])                                           #MANDATORY PARAMETER - FIXED VALUE -> l3ipvlan?
    Device_2_IF_index       = IntegerField('Device_2 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")])     #MANDATORY PARAMETER
    Device_2_IF_vlan_id     = IntegerField('Device_2 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")])              #MANDATORY PARAMETER 
    Device_2_IF_mtu         = IntegerField('Device_2 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")])                #MANDATORY PARAMETER - FIXED VALUE -> 3000?
    Device_2_IF_address_ip  = StringField('Device_2 IP Address', validators=[CustomInputRequired(), validate_ipv4_address])                                             #MANDATORY PARAMETER                                                    
    Device_2_IF_address_prefix = IntegerField('Device_2 IP Prefix length', validators=[CustomInputRequired(), validate_uint32])                                         #MANDATORY PARAMETER       
    Device_2_IF_description = StringField ('Device_2 SubIF Description', validators=[Optional()])                                                                       #OPTIONAL  PARAMETER                                                                                              
    
    ## Routing Policy (RP) parameters
    #RP_policy_name    = StringField('Policy Name', validators=[InputRequired()])                                                                #MANDATORY PARAMETER
    #RP_statement_name = StringField('Statement Name', validators=[InputRequired()])                                                             #MANDATORY PARAMETER
    #RP_policy_result  = SelectField('Policy Result', choices=[(None, 'Not Defined'), ('ACCEPT_ROUTE', 'ACCEPT_ROUTE'),('REJECT_ROUTE', 'REJECT_ROUTE')], validators=[Optional()])  
    #RP_ext_community_set_name = StringField('Ext Community Set Name', validators=[InputRequired()])                                             #MANDATORY PARAMETER
    #RP_ext_community_member   = StringField('Ext Community Member', validators=[InputRequired()])                                               #MANDATORY PARAMETER
                                                 
