# VGS Configuration

VGSConfiguration adds more power to your `VGSTextField`. Its' attributes are used to connect `VGSTextField` with specific `VGSCollect` instance, perform built-in validations and add additional features.

## VGS Configuration

### Declaration

```swift
class VGSConfiguration
```

### Creating a VGSConfiguration

```swift
init(collector vgs: VGSCollect, fieldName: String)
```

### VGSConfiguration attributes

| **Attribute**       | **Description**                                                                                                                                                     |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| fieldName           | Identifier for Redact/Reveal operations on Inbound/Outbound routes.                                                                                                 |
| isRequired          | Mark the field should be non-empty and non-nil on `VGSCollect.sendData(_:)` request. Default is **false**.                                                          |
| isRequiredValidOnly | Mark the field should be valid on `VGSCollect.sendData(_:)`. Default is **false**.                                                                                  |
| type                | `FieldType` used to define default field validation and formatting.                                                                                                 |
| formatPattern       | Input text mask pattern. If not set, will be used default masking for each `FieldType`.                                                                             |
| divider             | Divider string replace spaces or other characters in input string based on `formatPattern`. Replacement will be done during `sendData(_:)` request.                 |
| keyboardType        | Requests that a particular keyboard type be displayed when a textfield becomes first responder. If not set, will be used default keyboardType for each `FieldType`. |
| returnKeyType       | Keyboard return key.                                                                                                                                                |
| keyboardAppearance  | Keyboard Appearance Type, default is \`\`UIKeyboardAppearance.default`.`                                                                                            |
| validationRules     | A set of rules that will be applied for input validation. If `nil`, default validation rules will be applied.                                                       |
| maxInputLength      | Limit max text input length, default is `.nil`.                                                                                                                     |

Some of VGSConfiguration attribites are used to create rules for input data validation. You can check validation results represented in a `State` object.

> • When `FieldType` is **not none**, default validation will be applied to input data.\
> • When `isRequired` set as **true**, input data is **empty** or **nil** - `VGSCollect.sendData(_:)` request will return error.\
> • When `isRequiredValidOnly` set as **true**, input data is **not valid** - `VGSCollect.sendData(_:)` request will return error.\
> • For **.expCardDate** `FieldType` default `divider` is **/** character and for **.ssn** type is **-** character. For other `FieldTypes` it's empty string.\\

### VGSConfiguration FieldType

| **FieldType**     | **Description**                                                     |
| ----------------- | ------------------------------------------------------------------- |
| `.cardNumber`     | - input field for the card number                                   |
| `.cvc`            | - input field for card security code                                |
| `.date`           | - input field for the date                                          |
| `.expDate`        | - input field for the card expiration date                          |
| `.cardHolderName` | - input field for cardHolderName                                    |
| `.ssn`            | - input field for US Social Security Number                         |
| `.none`           | - input field for any type of text input with no default validation |

You can check default validation details for each specific field type [here](https://www.verygoodsecurity.com/docs/vgs-collect/ios-sdk/error-handling).

If you didn't find specific `FieldType` for your use case, you can always configure `VGSTextField` with `VGSConfiguration.fieldType = .none`. Then assign any specific rule set to the field and use other configuration attributes.

### VGSConfiguration formatPattern

The **formatPattern** string will be applied as a mask on the user input text. It also works as input characters filter.\
This pattern can be used only for visual input format in `VGSTextField`. It doesn't have an impact on input data format when you send it to VGS. In case you need to send data with additional characters, check the `Divider` section.

| **Format** | **Description**                     |              | **Example** |           |
| ---------- | ----------------------------------- | ------------ | ----------- | --------- |
| `*`        | Letters and Digits replacement char | "UA12345vgs" | `**-***`    | "UA-123"  |
| `@`        | Any letter replacement char         | "UA12345vgs" | `@@_@@@`    | "UA\_vgs" |
| `a`        | Lowercase replacement char          | "UA12345vgs" | `aaa`       | "vgs"     |
| `A`        | Uppercase replacement char          | "UA12345vgs" | `AAA`       | "UA"      |
| `#`        | Digits replacement char             | "UA12345vgs" | `#/##/##`   | "1/23/45" |

> • You can only use **non-alphaNumeric** characters as dividers in the `formatPattern` string.\
> • The `formatPattern` will not be applied to the **.cvc** `FieldType`.\
> • For more **.date** formats check `VGSDateConfiguration`.\
> • For the **.expCardDate** `FieldType` it is only allowed to set date format as `##/##` or `##/####` (that will represent `MM/YY` or `MM/YYYY` format). Changing format to `##/####` will also require field validation rule update. In other cases, the field validation `State` will fail.\
> • For more **.expCardDate** date formats check `VGSExpDateConfiguration`.

> • When you change default field `formatPattern`, check & update default validation rules for the field if needed.\
> • Characters used for describing `formatPattern` will be ignored during input validation and **sendData(\_:)** request.

### VGSConfiguration Divider

Use the `divider` if you need to replace characters in the input text. Characters will be replaced based on `formatPattern` when data are being sent to VGS.

### Examples

```swift
// ...

/// Example 1
configuration.formatPattern = "#### #### #### ####"
configuration.divider = "-"

user input: "4111111111111111"
textfield format: "4111 1111 1111 1111"
sending format: "4111-1111-1111-1111"

/// Example 2
configuration.formatPattern = "##/##/##"
configuration.divider = ":"

user input: "122030"
textfield format: "12/20/30"
sending format: "12:20:30"

// Example 3
configuration.formatPattern = "**-***"
configuration.divider = "//"

user input: "UA123"
textfield format: "UA-123"
sending format: "UA//123"

```

> • If `formatPattern` is empty string, then `divider` will be not applied.\
> • Characters used as `divider` will be ignored during input validation.

## VGSExpDateConfiguration

`VGSExpDateConfiguration` class extends `VGSConfiguration` with more specific settings for fields with type `FieldType.expDate`.

### Declaration

```swift
class VGSExpDateConfiguration: VGSConfiguration
```

### Creating a VGSExpDateConfiguration

```swift
init(collector vgs: VGSCollect, fieldName: String)
```

### VGSExpDateConfiguration attributes

| **Attribute**    | **Description**                                                                                   |
| ---------------- | ------------------------------------------------------------------------------------------------- |
| inputSource      | VGSTextFieldInputSource - date input source type, could be **.keyboard** or **.datePicker**.      |
| inputDateFormat  | VGSCardExpDateFormat - date format that user use for date input.                                  |
| outputDateFormat | VGSCardExpDateFormat - date format that will be send to your Vault.                               |
| serializers      | \[VGSFormatSerializerProtocol] - an array of serializers to format data being sent to the server. |

### VGSCardExpDateFormat available options

| **VGSCardExpDateFormat** | **Date Format** | **Input Format Pattern** |
| ------------------------ | --------------- | ------------------------ |
| `.shortYear`             | `mm/yy`         | `##/##`                  |
| `.longYear`              | `mm/yyyy`       | `##/####`                |
| `.shortYearThenMonth`    | `yy/mm`         | `##/##`                  |
| `.longYearThenMonth`     | `yyyy/mm`       | `####/##`                |

> • Changing `.inputDateFormat` could require field `VGSValidationRuleCardExpirationDate` rule updates(default validation expects `.shortYear` as field input format).\\

### Change Output Date format

You can change date format when sending data to your backend by setting `VGSExpDateConfiguration.outputDateFormat` in field configuration.

### Code example

```swift
/// Change output card expiration date format form "mm/yy" to "mm/yyyy"

/// Use `VGSExpDateConfiguration` when you need to convert output date format
let expDateConfiguration = VGSExpDateConfiguration(collector: vgsCollect, fieldName: "card_expirationDate")
expDateConfiguration.type = .expDate
expDateConfiguration.divider = "/"
expDateConfiguration.formatPattern = "##/##"

/// Set date format that user use for input
expDateConfiguration.inputDateFormat = .shortYear // "mm/yy" -> 01/25

/// Set  date format that will be send to your Vault
expDateConfiguration.outputDateFormat = .longYear // "mm/yyyy" -> 01/2025

....

/// Change output card expiration date format from "mm/yy" to "yyyy/mm"
let expDateConfiguration = VGSExpDateConfiguration(collector: vgsCollect, fieldName: "card_expirationDate")
expDateConfiguration.type = .expDate
expDateConfiguration.divider = "/"
expDateConfiguration.formatPattern = "##/##"

/// Set  date format that user use for input
expDateConfiguration.inputDateFormat = .shortYear //  "mm/yyyy" -> 01/2025

/// Set  date format that will be send to your Vault
expDateConfiguration.outputDateFormat = .longYearThenMonth // "yyyy/mm" -> 2025/01

/// Update validation rules(default validation expects .shortYear)
expDateConfiguration.validationRules = VGSValidationRuleSet(rules: [
  VGSValidationRuleCardExpirationDate(dateFormat: .shortYear, error: VGSValidationErrorType.expDate.rawValue)
])
```

> • To change output date format you should setup both **.inputDateFormat** and **outputDateFormat**.\
> • For validation, VGSCollect use input from VGSTextField.\\

### Separate Expiration Date Components

You can send expiration month and year as different fields. This could be done with `VGSExpDateSeparateSerializer`.

## Code example

```swift
/// Setup `VGSExpDateConfiguration` for you field
let expDateConfiguration = VGSExpDateConfiguration(collector: vgsCollect, fieldName: "card_expirationDate")
expDateConfiguration.type = .expDate

/// Setup VGSExpDateSeparateSerializer with specific fieldNames for month and year date components
let expDateSerializer = VGSExpDateSeparateSerializer(monthFieldName: "card_date.month", yearFieldName: "card_date.year")
expDateConfiguration.serializers = [expDateSerializer]
```

**JSON to submit:**

```json
/// The result JSON for input date 03/25 will have next structure:
"card_date" : {
  "year" : "25",
  "month" : "03"
}
```

If you need more advanced options to customise JSON structure, check our examples [here](https://docs.verygoodsecurity.com/vault/developer-tools/vgs-collect/submit-data#advanced-settings).

### VGSConfiguration maxInputLength

You can limit max text input length with `.maxInputLength` option.

## Code example

```swift
/// Setup
 let cityFieldConfiguration = VGSConfiguration(collector: vgsCollect, fieldName: "city")
 cityFieldConfiguration.maxInputLength = 32
```

> • Setting both `.formatPattern` and `.maxInputLength` options may cause unpredictable issues with text formatting.\\

## VGSDateConfiguration

`VGSDateConfiguration` class extends `VGSConfiguration` with more specific settings for fields with type `FieldType.date`.

### Declaration

```swift
class VGSDateConfiguration: VGSConfiguration
```

### Creating a VGSDateConfiguration

```swift
init(collector vgs: VGSCollect, fieldName: String, datePickerStartDate: VGSDate? = nil, datePickerEndDate: VGSDate? = nil)
```

> • If `datePickerStartDate` or `datePickerEndDate` are not set, the configuration will use the default dates as:\
> `datePickerStartDate`: Today minus 100 years.\
> `datePickerEndDate`: Today plus 100 years.\
> • You should use the same `.datePickerStartDate` and `.datePickerStartDate` of the configuration in the `.start` and `.end` dates of the validation rule `VGSValidationRuleDateRange`. Using different dates could lead in unexpected results.\\

### VGSDateConfiguration attributes

| **Attribute**    | **Description**                                                                                                          |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------ |
| inputSource      | VGSTextFieldInputSource - date input source type, could be **.keyboard** or **.datePicker**. Defaults to **.datePicker** |
| inputDateFormat  | VGSDateFormat - date format that user use for date input.                                                                |
| outputDateFormat | VGSDateFormat - date format that will be send to your Vault.                                                             |
| serializers      | \[VGSFormatSerializerProtocol] - an array of serializers to format data being sent to the server.                        |

### VGSDateFormat available options

| **VGSDateFormat** | **Date Format** | **Input Format Pattern** |
| ----------------- | --------------- | ------------------------ |
| `.mmddyyyy`       | `mm-dd-yyyy`    | `##-##-####`             |
| `.ddmmyyyy`       | `dd-mm-yyyy`    | `##-##-####`             |
| `.yyyymmdd`       | `yyyy-mm-dd`    | `####-##-##`             |

> • You should use the same `.inputDateFormat` of the configuration in the `.dateFormat` of the validation rule `VGSValidationRuleDateRange`. Using different formats could lead in unexpected results.\\

### Change Output Date format

You can change date format when sending data to your backend by setting `VGSDateConfiguration.outputDateFormat` in field configuration.

### Code example

```swift
/// Change output date format from "mm/dd/yyyy" to "yyyy/mm/dd"

/// Use `VGSDateConfiguration` when you need to convert output date format
let dateConfiguration = VGSDateConfiguration(collector: vgsCollect, fieldName: "date")
dateConfiguration.type = .date
dateConfiguration.divider = "/"
dateConfiguration.formatPattern = "##/##/####"

/// Set date format that user use for input
dateConfiguration.inputDateFormat = .mmddyyyy // "mm/dd/yyyy" -> 01/02/2025

/// Set date format that will be send to your Vault
dateConfiguration.outputDateFormat = .yyyymmdd // "yyyy/mm/dd" -> 2025/01/02

/// Update validation rules, date format should be the same used in the configuration inputDateFormat
dateConfiguration.validationRules = VGSValidationRuleSet(
  rules: [
    VGSValidationRuleDateRange(
      dateFormat: .mmddyyyy,
      error: VGSValidationErrorType.date.rawValue
    )
  ]
)
```

### Change validation range dates

You can set a range to validate the input added to `VGSDateTextField`. You can set the start date, end date or none of them. To set the range, use the `VGSDateConfiguration` constructor to pass the `datePickerStartDate` and `datePickerEndDate`. Also, you need to add a validation rule `VGSValidationRuleDateRange` using exactly the same `start` and `end` dates.

### Code example

```swift

/// Define range validation
/// The validation will fails if the date is before 01/01/2010 or after 01/01/2020
let startDate = VGSDate(day: 1, month: 1, year: 2010)
let endDate = VGSDate(day: 1, month: 1, year: 2020)

/// Use `VGSDateConfiguration` when you need to set validation date range
let dateConfiguration = VGSDateConfiguration(
  collector: vgsCollect,
  fieldName: "date",
  datePickerStartDate: startDate,
  datePickerEndDate: endDate
)

// ...

/// Update validation rules, `start` and `end` should be the same used in the configuration `datePickerStartDate` and `datePickerEndDate`
dateConfiguration.validationRules = VGSValidationRuleSet(
  rules: [
    VGSValidationRuleDateRange(
      dateFormat: .mmddyyyy,
      error: VGSValidationErrorType.date.rawValue,
      start: startDate
      end: endDate
    )
  ]
)
```

> • To change output date format you should setup both **.inputDateFormat** and **outputDateFormat**.\
> • For validation, VGSCollect use input from VGSTextField.\\

### Separate Date Components

You can send day, month and year as different fields. This could be done with `VGSDateSeparateSerializer`.

## Code example

```swift
/// Setup `VGSDateConfiguration` for you field
let dateConfiguration = VGSDateConfiguration(collector: vgsCollect, fieldName: "date")
dateConfiguration.type = .date
dateConfiguration.inputDateFormat = .ddmmyyyy

/// Setup VGSDateSeparateSerializer with specific fieldNames for day, month and year date components
let dateSerializer = VGSDateSeparateSerializer(
    dayFieldName: "date.day",
    monthFieldName: "date.month",
    yearFieldName: "date.year"
)
dateConfiguration.serializers = [dateSerializer]
```

**JSON to submit:**

```json
/// The result JSON for input date 01/03/2025 will have next structure:
"date" : {
  "day": "01",
  "month" : "03",
  "year" : "2025"
}
```
