<?php

/**
 * Adyen Payment API
 *
 * The version of the OpenAPI document: 68
 * Generated by: https://openapi-generator.tech
 * OpenAPI Generator version: 6.0.1
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */


namespace Adyen\Model\Payments;

use \ArrayAccess;
use Adyen\Model\Payments\ObjectSerializer;

/**
 * PaymentRequest3d Class Doc Comment
 *
 * @category Class
 * @package  Adyen
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 * @implements \ArrayAccess<string, mixed>
 */
class PaymentRequest3d implements ModelInterface, ArrayAccess, \JsonSerializable
{
    public const DISCRIMINATOR = null;

    /**
      * The original name of the model.
      *
      * @var string
      */
    protected static $openAPIModelName = 'PaymentRequest3d';

    /**
      * Array of property to type mappings. Used for (de)serialization
      *
      * @var string[]
      */
    protected static $openAPITypes = [
        'accountInfo' => '\Adyen\Model\Payments\AccountInfo',
        'additionalAmount' => '\Adyen\Model\Payments\Amount',
        'additionalData' => 'array<string,string>',
        'amount' => '\Adyen\Model\Payments\Amount',
        'applicationInfo' => '\Adyen\Model\Payments\ApplicationInfo',
        'billingAddress' => '\Adyen\Model\Payments\Address',
        'browserInfo' => '\Adyen\Model\Payments\BrowserInfo',
        'captureDelayHours' => 'int',
        'dateOfBirth' => '\DateTime',
        'dccQuote' => '\Adyen\Model\Payments\ForexQuote',
        'deliveryAddress' => '\Adyen\Model\Payments\Address',
        'deliveryDate' => '\DateTime',
        'deviceFingerprint' => 'string',
        'fraudOffset' => 'int',
        'installments' => '\Adyen\Model\Payments\Installments',
        'localizedShopperStatement' => 'array<string,string>',
        'mcc' => 'string',
        'md' => 'string',
        'merchantAccount' => 'string',
        'merchantOrderReference' => 'string',
        'merchantRiskIndicator' => '\Adyen\Model\Payments\MerchantRiskIndicator',
        'metadata' => 'array<string,string>',
        'orderReference' => 'string',
        'paResponse' => 'string',
        'recurring' => '\Adyen\Model\Payments\Recurring',
        'recurringProcessingModel' => 'string',
        'reference' => 'string',
        'selectedBrand' => 'string',
        'selectedRecurringDetailReference' => 'string',
        'sessionId' => 'string',
        'shopperEmail' => 'string',
        'shopperIP' => 'string',
        'shopperInteraction' => 'string',
        'shopperLocale' => 'string',
        'shopperName' => '\Adyen\Model\Payments\Name',
        'shopperReference' => 'string',
        'shopperStatement' => 'string',
        'socialSecurityNumber' => 'string',
        'splits' => '\Adyen\Model\Payments\Split[]',
        'store' => 'string',
        'telephoneNumber' => 'string',
        'threeDS2RequestData' => '\Adyen\Model\Payments\ThreeDS2RequestData',
        'threeDSAuthenticationOnly' => 'bool',
        'totalsGroup' => 'string',
        'trustedShopper' => 'bool'
    ];

    /**
      * Array of property to format mappings. Used for (de)serialization
      *
      * @var string[]
      * @phpstan-var array<string, string|null>
      * @psalm-var array<string, string|null>
      */
    protected static $openAPIFormats = [
        'accountInfo' => null,
        'additionalAmount' => null,
        'additionalData' => null,
        'amount' => null,
        'applicationInfo' => null,
        'billingAddress' => null,
        'browserInfo' => null,
        'captureDelayHours' => 'int32',
        'dateOfBirth' => 'date',
        'dccQuote' => null,
        'deliveryAddress' => null,
        'deliveryDate' => 'date-time',
        'deviceFingerprint' => null,
        'fraudOffset' => 'int32',
        'installments' => null,
        'localizedShopperStatement' => null,
        'mcc' => null,
        'md' => null,
        'merchantAccount' => null,
        'merchantOrderReference' => null,
        'merchantRiskIndicator' => null,
        'metadata' => null,
        'orderReference' => null,
        'paResponse' => null,
        'recurring' => null,
        'recurringProcessingModel' => null,
        'reference' => null,
        'selectedBrand' => null,
        'selectedRecurringDetailReference' => null,
        'sessionId' => null,
        'shopperEmail' => null,
        'shopperIP' => null,
        'shopperInteraction' => null,
        'shopperLocale' => null,
        'shopperName' => null,
        'shopperReference' => null,
        'shopperStatement' => null,
        'socialSecurityNumber' => null,
        'splits' => null,
        'store' => null,
        'telephoneNumber' => null,
        'threeDS2RequestData' => null,
        'threeDSAuthenticationOnly' => null,
        'totalsGroup' => null,
        'trustedShopper' => null
    ];

    /**
      * Array of nullable properties. Used for (de)serialization
      *
      * @var boolean[]
      */
    protected static $openAPINullables = [
        'accountInfo' => false,
        'additionalAmount' => false,
        'additionalData' => false,
        'amount' => false,
        'applicationInfo' => false,
        'billingAddress' => false,
        'browserInfo' => false,
        'captureDelayHours' => true,
        'dateOfBirth' => false,
        'dccQuote' => false,
        'deliveryAddress' => false,
        'deliveryDate' => false,
        'deviceFingerprint' => false,
        'fraudOffset' => true,
        'installments' => false,
        'localizedShopperStatement' => false,
        'mcc' => false,
        'md' => false,
        'merchantAccount' => false,
        'merchantOrderReference' => false,
        'merchantRiskIndicator' => false,
        'metadata' => false,
        'orderReference' => false,
        'paResponse' => false,
        'recurring' => false,
        'recurringProcessingModel' => false,
        'reference' => false,
        'selectedBrand' => false,
        'selectedRecurringDetailReference' => false,
        'sessionId' => false,
        'shopperEmail' => false,
        'shopperIP' => false,
        'shopperInteraction' => false,
        'shopperLocale' => false,
        'shopperName' => false,
        'shopperReference' => false,
        'shopperStatement' => false,
        'socialSecurityNumber' => false,
        'splits' => false,
        'store' => false,
        'telephoneNumber' => false,
        'threeDS2RequestData' => false,
        'threeDSAuthenticationOnly' => false,
        'totalsGroup' => false,
        'trustedShopper' => false
    ];

    /**
      * If a nullable field gets set to null, insert it here
      *
      * @var boolean[]
      */
    protected $openAPINullablesSetToNull = [];

    /**
     * Array of property to type mappings. Used for (de)serialization
     *
     * @return array
     */
    public static function openAPITypes()
    {
        return self::$openAPITypes;
    }

    /**
     * Array of property to format mappings. Used for (de)serialization
     *
     * @return array
     */
    public static function openAPIFormats()
    {
        return self::$openAPIFormats;
    }

    /**
     * Array of nullable properties
     *
     * @return array
     */
    protected static function openAPINullables(): array
    {
        return self::$openAPINullables;
    }

    /**
     * Array of nullable field names deliberately set to null
     *
     * @return boolean[]
     */
    private function getOpenAPINullablesSetToNull(): array
    {
        return $this->openAPINullablesSetToNull;
    }

    /**
     * Setter - Array of nullable field names deliberately set to null
     *
     * @param boolean[] $openAPINullablesSetToNull
     */
    private function setOpenAPINullablesSetToNull(array $openAPINullablesSetToNull): void
    {
        $this->openAPINullablesSetToNull = $openAPINullablesSetToNull;
    }

    /**
     * Checks if a property is nullable
     *
     * @param string $property
     * @return bool
     */
    public static function isNullable(string $property): bool
    {
        return self::openAPINullables()[$property] ?? false;
    }

    /**
     * Checks if a nullable property is set to null.
     *
     * @param string $property
     * @return bool
     */
    public function isNullableSetToNull(string $property): bool
    {
        return in_array($property, $this->getOpenAPINullablesSetToNull(), true);
    }

    /**
     * Array of attributes where the key is the local name,
     * and the value is the original name
     *
     * @var string[]
     */
    protected static $attributeMap = [
        'accountInfo' => 'accountInfo',
        'additionalAmount' => 'additionalAmount',
        'additionalData' => 'additionalData',
        'amount' => 'amount',
        'applicationInfo' => 'applicationInfo',
        'billingAddress' => 'billingAddress',
        'browserInfo' => 'browserInfo',
        'captureDelayHours' => 'captureDelayHours',
        'dateOfBirth' => 'dateOfBirth',
        'dccQuote' => 'dccQuote',
        'deliveryAddress' => 'deliveryAddress',
        'deliveryDate' => 'deliveryDate',
        'deviceFingerprint' => 'deviceFingerprint',
        'fraudOffset' => 'fraudOffset',
        'installments' => 'installments',
        'localizedShopperStatement' => 'localizedShopperStatement',
        'mcc' => 'mcc',
        'md' => 'md',
        'merchantAccount' => 'merchantAccount',
        'merchantOrderReference' => 'merchantOrderReference',
        'merchantRiskIndicator' => 'merchantRiskIndicator',
        'metadata' => 'metadata',
        'orderReference' => 'orderReference',
        'paResponse' => 'paResponse',
        'recurring' => 'recurring',
        'recurringProcessingModel' => 'recurringProcessingModel',
        'reference' => 'reference',
        'selectedBrand' => 'selectedBrand',
        'selectedRecurringDetailReference' => 'selectedRecurringDetailReference',
        'sessionId' => 'sessionId',
        'shopperEmail' => 'shopperEmail',
        'shopperIP' => 'shopperIP',
        'shopperInteraction' => 'shopperInteraction',
        'shopperLocale' => 'shopperLocale',
        'shopperName' => 'shopperName',
        'shopperReference' => 'shopperReference',
        'shopperStatement' => 'shopperStatement',
        'socialSecurityNumber' => 'socialSecurityNumber',
        'splits' => 'splits',
        'store' => 'store',
        'telephoneNumber' => 'telephoneNumber',
        'threeDS2RequestData' => 'threeDS2RequestData',
        'threeDSAuthenticationOnly' => 'threeDSAuthenticationOnly',
        'totalsGroup' => 'totalsGroup',
        'trustedShopper' => 'trustedShopper'
    ];

    /**
     * Array of attributes to setter functions (for deserialization of responses)
     *
     * @var string[]
     */
    protected static $setters = [
        'accountInfo' => 'setAccountInfo',
        'additionalAmount' => 'setAdditionalAmount',
        'additionalData' => 'setAdditionalData',
        'amount' => 'setAmount',
        'applicationInfo' => 'setApplicationInfo',
        'billingAddress' => 'setBillingAddress',
        'browserInfo' => 'setBrowserInfo',
        'captureDelayHours' => 'setCaptureDelayHours',
        'dateOfBirth' => 'setDateOfBirth',
        'dccQuote' => 'setDccQuote',
        'deliveryAddress' => 'setDeliveryAddress',
        'deliveryDate' => 'setDeliveryDate',
        'deviceFingerprint' => 'setDeviceFingerprint',
        'fraudOffset' => 'setFraudOffset',
        'installments' => 'setInstallments',
        'localizedShopperStatement' => 'setLocalizedShopperStatement',
        'mcc' => 'setMcc',
        'md' => 'setMd',
        'merchantAccount' => 'setMerchantAccount',
        'merchantOrderReference' => 'setMerchantOrderReference',
        'merchantRiskIndicator' => 'setMerchantRiskIndicator',
        'metadata' => 'setMetadata',
        'orderReference' => 'setOrderReference',
        'paResponse' => 'setPaResponse',
        'recurring' => 'setRecurring',
        'recurringProcessingModel' => 'setRecurringProcessingModel',
        'reference' => 'setReference',
        'selectedBrand' => 'setSelectedBrand',
        'selectedRecurringDetailReference' => 'setSelectedRecurringDetailReference',
        'sessionId' => 'setSessionId',
        'shopperEmail' => 'setShopperEmail',
        'shopperIP' => 'setShopperIP',
        'shopperInteraction' => 'setShopperInteraction',
        'shopperLocale' => 'setShopperLocale',
        'shopperName' => 'setShopperName',
        'shopperReference' => 'setShopperReference',
        'shopperStatement' => 'setShopperStatement',
        'socialSecurityNumber' => 'setSocialSecurityNumber',
        'splits' => 'setSplits',
        'store' => 'setStore',
        'telephoneNumber' => 'setTelephoneNumber',
        'threeDS2RequestData' => 'setThreeDS2RequestData',
        'threeDSAuthenticationOnly' => 'setThreeDSAuthenticationOnly',
        'totalsGroup' => 'setTotalsGroup',
        'trustedShopper' => 'setTrustedShopper'
    ];

    /**
     * Array of attributes to getter functions (for serialization of requests)
     *
     * @var string[]
     */
    protected static $getters = [
        'accountInfo' => 'getAccountInfo',
        'additionalAmount' => 'getAdditionalAmount',
        'additionalData' => 'getAdditionalData',
        'amount' => 'getAmount',
        'applicationInfo' => 'getApplicationInfo',
        'billingAddress' => 'getBillingAddress',
        'browserInfo' => 'getBrowserInfo',
        'captureDelayHours' => 'getCaptureDelayHours',
        'dateOfBirth' => 'getDateOfBirth',
        'dccQuote' => 'getDccQuote',
        'deliveryAddress' => 'getDeliveryAddress',
        'deliveryDate' => 'getDeliveryDate',
        'deviceFingerprint' => 'getDeviceFingerprint',
        'fraudOffset' => 'getFraudOffset',
        'installments' => 'getInstallments',
        'localizedShopperStatement' => 'getLocalizedShopperStatement',
        'mcc' => 'getMcc',
        'md' => 'getMd',
        'merchantAccount' => 'getMerchantAccount',
        'merchantOrderReference' => 'getMerchantOrderReference',
        'merchantRiskIndicator' => 'getMerchantRiskIndicator',
        'metadata' => 'getMetadata',
        'orderReference' => 'getOrderReference',
        'paResponse' => 'getPaResponse',
        'recurring' => 'getRecurring',
        'recurringProcessingModel' => 'getRecurringProcessingModel',
        'reference' => 'getReference',
        'selectedBrand' => 'getSelectedBrand',
        'selectedRecurringDetailReference' => 'getSelectedRecurringDetailReference',
        'sessionId' => 'getSessionId',
        'shopperEmail' => 'getShopperEmail',
        'shopperIP' => 'getShopperIP',
        'shopperInteraction' => 'getShopperInteraction',
        'shopperLocale' => 'getShopperLocale',
        'shopperName' => 'getShopperName',
        'shopperReference' => 'getShopperReference',
        'shopperStatement' => 'getShopperStatement',
        'socialSecurityNumber' => 'getSocialSecurityNumber',
        'splits' => 'getSplits',
        'store' => 'getStore',
        'telephoneNumber' => 'getTelephoneNumber',
        'threeDS2RequestData' => 'getThreeDS2RequestData',
        'threeDSAuthenticationOnly' => 'getThreeDSAuthenticationOnly',
        'totalsGroup' => 'getTotalsGroup',
        'trustedShopper' => 'getTrustedShopper'
    ];

    /**
     * Array of attributes where the key is the local name,
     * and the value is the original name
     *
     * @return array
     */
    public static function attributeMap()
    {
        return self::$attributeMap;
    }

    /**
     * Array of attributes to setter functions (for deserialization of responses)
     *
     * @return array
     */
    public static function setters()
    {
        return self::$setters;
    }

    /**
     * Array of attributes to getter functions (for serialization of requests)
     *
     * @return array
     */
    public static function getters()
    {
        return self::$getters;
    }

    /**
     * The original name of the model.
     *
     * @return string
     */
    public function getModelName()
    {
        return self::$openAPIModelName;
    }

    public const RECURRING_PROCESSING_MODEL_CARD_ON_FILE = 'CardOnFile';
    public const RECURRING_PROCESSING_MODEL_SUBSCRIPTION = 'Subscription';
    public const RECURRING_PROCESSING_MODEL_UNSCHEDULED_CARD_ON_FILE = 'UnscheduledCardOnFile';
    public const SHOPPER_INTERACTION_ECOMMERCE = 'Ecommerce';
    public const SHOPPER_INTERACTION_CONT_AUTH = 'ContAuth';
    public const SHOPPER_INTERACTION_MOTO = 'Moto';
    public const SHOPPER_INTERACTION_POS = 'POS';

    /**
     * Gets allowable values of the enum
     *
     * @return string[]
     */
    public function getRecurringProcessingModelAllowableValues()
    {
        return [
            self::RECURRING_PROCESSING_MODEL_CARD_ON_FILE,
            self::RECURRING_PROCESSING_MODEL_SUBSCRIPTION,
            self::RECURRING_PROCESSING_MODEL_UNSCHEDULED_CARD_ON_FILE,
        ];
    }
    /**
     * Gets allowable values of the enum
     *
     * @return string[]
     */
    public function getShopperInteractionAllowableValues()
    {
        return [
            self::SHOPPER_INTERACTION_ECOMMERCE,
            self::SHOPPER_INTERACTION_CONT_AUTH,
            self::SHOPPER_INTERACTION_MOTO,
            self::SHOPPER_INTERACTION_POS,
        ];
    }
    /**
     * Associative array for storing property values
     *
     * @var mixed[]
     */
    protected $container = [];

    /**
     * Constructor
     *
     * @param mixed[] $data Associated array of property values
     *                      initializing the model
     */
    public function __construct(array $data = null)
    {
        $this->setIfExists('accountInfo', $data ?? [], null);
        $this->setIfExists('additionalAmount', $data ?? [], null);
        $this->setIfExists('additionalData', $data ?? [], null);
        $this->setIfExists('amount', $data ?? [], null);
        $this->setIfExists('applicationInfo', $data ?? [], null);
        $this->setIfExists('billingAddress', $data ?? [], null);
        $this->setIfExists('browserInfo', $data ?? [], null);
        $this->setIfExists('captureDelayHours', $data ?? [], null);
        $this->setIfExists('dateOfBirth', $data ?? [], null);
        $this->setIfExists('dccQuote', $data ?? [], null);
        $this->setIfExists('deliveryAddress', $data ?? [], null);
        $this->setIfExists('deliveryDate', $data ?? [], null);
        $this->setIfExists('deviceFingerprint', $data ?? [], null);
        $this->setIfExists('fraudOffset', $data ?? [], null);
        $this->setIfExists('installments', $data ?? [], null);
        $this->setIfExists('localizedShopperStatement', $data ?? [], null);
        $this->setIfExists('mcc', $data ?? [], null);
        $this->setIfExists('md', $data ?? [], null);
        $this->setIfExists('merchantAccount', $data ?? [], null);
        $this->setIfExists('merchantOrderReference', $data ?? [], null);
        $this->setIfExists('merchantRiskIndicator', $data ?? [], null);
        $this->setIfExists('metadata', $data ?? [], null);
        $this->setIfExists('orderReference', $data ?? [], null);
        $this->setIfExists('paResponse', $data ?? [], null);
        $this->setIfExists('recurring', $data ?? [], null);
        $this->setIfExists('recurringProcessingModel', $data ?? [], null);
        $this->setIfExists('reference', $data ?? [], null);
        $this->setIfExists('selectedBrand', $data ?? [], null);
        $this->setIfExists('selectedRecurringDetailReference', $data ?? [], null);
        $this->setIfExists('sessionId', $data ?? [], null);
        $this->setIfExists('shopperEmail', $data ?? [], null);
        $this->setIfExists('shopperIP', $data ?? [], null);
        $this->setIfExists('shopperInteraction', $data ?? [], null);
        $this->setIfExists('shopperLocale', $data ?? [], null);
        $this->setIfExists('shopperName', $data ?? [], null);
        $this->setIfExists('shopperReference', $data ?? [], null);
        $this->setIfExists('shopperStatement', $data ?? [], null);
        $this->setIfExists('socialSecurityNumber', $data ?? [], null);
        $this->setIfExists('splits', $data ?? [], null);
        $this->setIfExists('store', $data ?? [], null);
        $this->setIfExists('telephoneNumber', $data ?? [], null);
        $this->setIfExists('threeDS2RequestData', $data ?? [], null);
        $this->setIfExists('threeDSAuthenticationOnly', $data ?? [], null);
        $this->setIfExists('totalsGroup', $data ?? [], null);
        $this->setIfExists('trustedShopper', $data ?? [], null);
    }

    /**
    * Sets $this->container[$variableName] to the given data or to the given default Value; if $variableName
    * is nullable and its value is set to null in the $fields array, then mark it as "set to null" in the
    * $this->openAPINullablesSetToNull array
    *
    * @param string $variableName
    * @param array  $fields
    * @param mixed  $defaultValue
    */
    private function setIfExists(string $variableName, array $fields, $defaultValue): void
    {
        if (self::isNullable($variableName) && array_key_exists($variableName, $fields) && is_null($fields[$variableName])) {
            $this->openAPINullablesSetToNull[] = $variableName;
        }

        $this->container[$variableName] = $fields[$variableName] ?? $defaultValue;
    }

    /**
     * Show all the invalid properties with reasons.
     *
     * @return array invalid properties with reasons
     */
    public function listInvalidProperties()
    {
        $invalidProperties = [];

        if ($this->container['md'] === null) {
            $invalidProperties[] = "'md' can't be null";
        }
        if ($this->container['merchantAccount'] === null) {
            $invalidProperties[] = "'merchantAccount' can't be null";
        }
        if ($this->container['paResponse'] === null) {
            $invalidProperties[] = "'paResponse' can't be null";
        }
        $allowedValues = $this->getRecurringProcessingModelAllowableValues();
        if (!is_null($this->container['recurringProcessingModel']) && !in_array($this->container['recurringProcessingModel'], $allowedValues, true)) {
            $invalidProperties[] = sprintf(
                "invalid value '%s' for 'recurringProcessingModel', must be one of '%s'",
                $this->container['recurringProcessingModel'],
                implode("', '", $allowedValues)
            );
        }

        $allowedValues = $this->getShopperInteractionAllowableValues();
        if (!is_null($this->container['shopperInteraction']) && !in_array($this->container['shopperInteraction'], $allowedValues, true)) {
            $invalidProperties[] = sprintf(
                "invalid value '%s' for 'shopperInteraction', must be one of '%s'",
                $this->container['shopperInteraction'],
                implode("', '", $allowedValues)
            );
        }

        return $invalidProperties;
    }

    /**
     * Validate all the properties in the model
     * return true if all passed
     *
     * @return bool True if all properties are valid
     */
    public function valid()
    {
        return count($this->listInvalidProperties()) === 0;
    }


    /**
     * Gets accountInfo
     *
     * @return \Adyen\Model\Payments\AccountInfo|null
     */
    public function getAccountInfo()
    {
        return $this->container['accountInfo'];
    }

    /**
     * Sets accountInfo
     *
     * @param \Adyen\Model\Payments\AccountInfo|null $accountInfo accountInfo
     *
     * @return self
     */
    public function setAccountInfo($accountInfo)
    {
        $this->container['accountInfo'] = $accountInfo;

        return $this;
    }

    /**
     * Gets additionalAmount
     *
     * @return \Adyen\Model\Payments\Amount|null
     */
    public function getAdditionalAmount()
    {
        return $this->container['additionalAmount'];
    }

    /**
     * Sets additionalAmount
     *
     * @param \Adyen\Model\Payments\Amount|null $additionalAmount additionalAmount
     *
     * @return self
     */
    public function setAdditionalAmount($additionalAmount)
    {
        $this->container['additionalAmount'] = $additionalAmount;

        return $this;
    }

    /**
     * Gets additionalData
     *
     * @return array<string,string>|null
     */
    public function getAdditionalData()
    {
        return $this->container['additionalData'];
    }

    /**
     * Sets additionalData
     *
     * @param array<string,string>|null $additionalData This field contains additional data, which may be required for a particular payment request.  The `additionalData` object consists of entries, each of which includes the key and value.
     *
     * @return self
     */
    public function setAdditionalData($additionalData)
    {
        $this->container['additionalData'] = $additionalData;

        return $this;
    }

    /**
     * Gets amount
     *
     * @return \Adyen\Model\Payments\Amount|null
     */
    public function getAmount()
    {
        return $this->container['amount'];
    }

    /**
     * Sets amount
     *
     * @param \Adyen\Model\Payments\Amount|null $amount amount
     *
     * @return self
     */
    public function setAmount($amount)
    {
        $this->container['amount'] = $amount;

        return $this;
    }

    /**
     * Gets applicationInfo
     *
     * @return \Adyen\Model\Payments\ApplicationInfo|null
     */
    public function getApplicationInfo()
    {
        return $this->container['applicationInfo'];
    }

    /**
     * Sets applicationInfo
     *
     * @param \Adyen\Model\Payments\ApplicationInfo|null $applicationInfo applicationInfo
     *
     * @return self
     */
    public function setApplicationInfo($applicationInfo)
    {
        $this->container['applicationInfo'] = $applicationInfo;

        return $this;
    }

    /**
     * Gets billingAddress
     *
     * @return \Adyen\Model\Payments\Address|null
     */
    public function getBillingAddress()
    {
        return $this->container['billingAddress'];
    }

    /**
     * Sets billingAddress
     *
     * @param \Adyen\Model\Payments\Address|null $billingAddress billingAddress
     *
     * @return self
     */
    public function setBillingAddress($billingAddress)
    {
        $this->container['billingAddress'] = $billingAddress;

        return $this;
    }

    /**
     * Gets browserInfo
     *
     * @return \Adyen\Model\Payments\BrowserInfo|null
     */
    public function getBrowserInfo()
    {
        return $this->container['browserInfo'];
    }

    /**
     * Sets browserInfo
     *
     * @param \Adyen\Model\Payments\BrowserInfo|null $browserInfo browserInfo
     *
     * @return self
     */
    public function setBrowserInfo($browserInfo)
    {
        $this->container['browserInfo'] = $browserInfo;

        return $this;
    }

    /**
     * Gets captureDelayHours
     *
     * @return int|null
     */
    public function getCaptureDelayHours()
    {
        return $this->container['captureDelayHours'];
    }

    /**
     * Sets captureDelayHours
     *
     * @param int|null $captureDelayHours The delay between the authorisation and scheduled auto-capture, specified in hours.
     *
     * @return self
     */
    public function setCaptureDelayHours($captureDelayHours)
    {
        $this->container['captureDelayHours'] = $captureDelayHours;

        return $this;
    }

    /**
     * Gets dateOfBirth
     *
     * @return \DateTime|null
     */
    public function getDateOfBirth()
    {
        return $this->container['dateOfBirth'];
    }

    /**
     * Sets dateOfBirth
     *
     * @param \DateTime|null $dateOfBirth The shopper's date of birth.  Format [ISO-8601](https://www.w3.org/TR/NOTE-datetime): YYYY-MM-DD
     *
     * @return self
     */
    public function setDateOfBirth($dateOfBirth)
    {
        $this->container['dateOfBirth'] = $dateOfBirth;

        return $this;
    }

    /**
     * Gets dccQuote
     *
     * @return \Adyen\Model\Payments\ForexQuote|null
     */
    public function getDccQuote()
    {
        return $this->container['dccQuote'];
    }

    /**
     * Sets dccQuote
     *
     * @param \Adyen\Model\Payments\ForexQuote|null $dccQuote dccQuote
     *
     * @return self
     */
    public function setDccQuote($dccQuote)
    {
        $this->container['dccQuote'] = $dccQuote;

        return $this;
    }

    /**
     * Gets deliveryAddress
     *
     * @return \Adyen\Model\Payments\Address|null
     */
    public function getDeliveryAddress()
    {
        return $this->container['deliveryAddress'];
    }

    /**
     * Sets deliveryAddress
     *
     * @param \Adyen\Model\Payments\Address|null $deliveryAddress deliveryAddress
     *
     * @return self
     */
    public function setDeliveryAddress($deliveryAddress)
    {
        $this->container['deliveryAddress'] = $deliveryAddress;

        return $this;
    }

    /**
     * Gets deliveryDate
     *
     * @return \DateTime|null
     */
    public function getDeliveryDate()
    {
        return $this->container['deliveryDate'];
    }

    /**
     * Sets deliveryDate
     *
     * @param \DateTime|null $deliveryDate The date and time the purchased goods should be delivered.  Format [ISO 8601](https://www.w3.org/TR/NOTE-datetime): YYYY-MM-DDThh:mm:ss.sssTZD  Example: 2017-07-17T13:42:40.428+01:00
     *
     * @return self
     */
    public function setDeliveryDate($deliveryDate)
    {
        $this->container['deliveryDate'] = $deliveryDate;

        return $this;
    }

    /**
     * Gets deviceFingerprint
     *
     * @return string|null
     */
    public function getDeviceFingerprint()
    {
        return $this->container['deviceFingerprint'];
    }

    /**
     * Sets deviceFingerprint
     *
     * @param string|null $deviceFingerprint A string containing the shopper's device fingerprint. For more information, refer to [Device fingerprinting](https://docs.adyen.com/risk-management/device-fingerprinting).
     *
     * @return self
     */
    public function setDeviceFingerprint($deviceFingerprint)
    {
        $this->container['deviceFingerprint'] = $deviceFingerprint;

        return $this;
    }

    /**
     * Gets fraudOffset
     *
     * @return int|null
     */
    public function getFraudOffset()
    {
        return $this->container['fraudOffset'];
    }

    /**
     * Sets fraudOffset
     *
     * @param int|null $fraudOffset An integer value that is added to the normal fraud score. The value can be either positive or negative.
     *
     * @return self
     */
    public function setFraudOffset($fraudOffset)
    {
        $this->container['fraudOffset'] = $fraudOffset;

        return $this;
    }

    /**
     * Gets installments
     *
     * @return \Adyen\Model\Payments\Installments|null
     */
    public function getInstallments()
    {
        return $this->container['installments'];
    }

    /**
     * Sets installments
     *
     * @param \Adyen\Model\Payments\Installments|null $installments installments
     *
     * @return self
     */
    public function setInstallments($installments)
    {
        $this->container['installments'] = $installments;

        return $this;
    }

    /**
     * Gets localizedShopperStatement
     *
     * @return array<string,string>|null
     */
    public function getLocalizedShopperStatement()
    {
        return $this->container['localizedShopperStatement'];
    }

    /**
     * Sets localizedShopperStatement
     *
     * @param array<string,string>|null $localizedShopperStatement The `localizedShopperStatement` field lets you use dynamic values for your shopper statement in a local character set. If not supplied, left empty, or for cross-border transactions, **shopperStatement** is used.  Adyen currently supports the ja-Kana character set for Visa and Mastercard payments in Japan using Japanese cards. This character set supports:  * UTF-8 based Katakana, capital letters, numbers and special characters.  * Half-width or full-width characters.
     *
     * @return self
     */
    public function setLocalizedShopperStatement($localizedShopperStatement)
    {
        $this->container['localizedShopperStatement'] = $localizedShopperStatement;

        return $this;
    }

    /**
     * Gets mcc
     *
     * @return string|null
     */
    public function getMcc()
    {
        return $this->container['mcc'];
    }

    /**
     * Sets mcc
     *
     * @param string|null $mcc The [merchant category code](https://en.wikipedia.org/wiki/Merchant_category_code) (MCC) is a four-digit number, which relates to a particular market segment. This code reflects the predominant activity that is conducted by the merchant.
     *
     * @return self
     */
    public function setMcc($mcc)
    {
        $this->container['mcc'] = $mcc;

        return $this;
    }

    /**
     * Gets md
     *
     * @return string
     */
    public function getMd()
    {
        return $this->container['md'];
    }

    /**
     * Sets md
     *
     * @param string $md The payment session identifier returned by the card issuer.
     *
     * @return self
     */
    public function setMd($md)
    {
        $this->container['md'] = $md;

        return $this;
    }

    /**
     * Gets merchantAccount
     *
     * @return string
     */
    public function getMerchantAccount()
    {
        return $this->container['merchantAccount'];
    }

    /**
     * Sets merchantAccount
     *
     * @param string $merchantAccount The merchant account identifier, with which you want to process the transaction.
     *
     * @return self
     */
    public function setMerchantAccount($merchantAccount)
    {
        $this->container['merchantAccount'] = $merchantAccount;

        return $this;
    }

    /**
     * Gets merchantOrderReference
     *
     * @return string|null
     */
    public function getMerchantOrderReference()
    {
        return $this->container['merchantOrderReference'];
    }

    /**
     * Sets merchantOrderReference
     *
     * @param string|null $merchantOrderReference This reference allows linking multiple transactions to each other for reporting purposes (i.e. order auth-rate). The reference should be unique per billing cycle. The same merchant order reference should never be reused after the first authorised attempt. If used, this field should be supplied for all incoming authorisations. > We strongly recommend you send the `merchantOrderReference` value to benefit from linking payment requests when authorisation retries take place. In addition, we recommend you provide `retry.orderAttemptNumber`, `retry.chainAttemptNumber`, and `retry.skipRetry` values in `PaymentRequest.additionalData`.
     *
     * @return self
     */
    public function setMerchantOrderReference($merchantOrderReference)
    {
        $this->container['merchantOrderReference'] = $merchantOrderReference;

        return $this;
    }

    /**
     * Gets merchantRiskIndicator
     *
     * @return \Adyen\Model\Payments\MerchantRiskIndicator|null
     */
    public function getMerchantRiskIndicator()
    {
        return $this->container['merchantRiskIndicator'];
    }

    /**
     * Sets merchantRiskIndicator
     *
     * @param \Adyen\Model\Payments\MerchantRiskIndicator|null $merchantRiskIndicator merchantRiskIndicator
     *
     * @return self
     */
    public function setMerchantRiskIndicator($merchantRiskIndicator)
    {
        $this->container['merchantRiskIndicator'] = $merchantRiskIndicator;

        return $this;
    }

    /**
     * Gets metadata
     *
     * @return array<string,string>|null
     */
    public function getMetadata()
    {
        return $this->container['metadata'];
    }

    /**
     * Sets metadata
     *
     * @param array<string,string>|null $metadata Metadata consists of entries, each of which includes a key and a value. Limits: * Maximum 20 key-value pairs per request. When exceeding, the \"177\" error occurs: \"Metadata size exceeds limit\". * Maximum 20 characters per key. * Maximum 80 characters per value.
     *
     * @return self
     */
    public function setMetadata($metadata)
    {
        $this->container['metadata'] = $metadata;

        return $this;
    }

    /**
     * Gets orderReference
     *
     * @return string|null
     */
    public function getOrderReference()
    {
        return $this->container['orderReference'];
    }

    /**
     * Sets orderReference
     *
     * @param string|null $orderReference When you are doing multiple partial (gift card) payments, this is the `pspReference` of the first payment. We use this to link the multiple payments to each other. As your own reference for linking multiple payments, use the `merchantOrderReference`instead.
     *
     * @return self
     */
    public function setOrderReference($orderReference)
    {
        $this->container['orderReference'] = $orderReference;

        return $this;
    }

    /**
     * Gets paResponse
     *
     * @return string
     */
    public function getPaResponse()
    {
        return $this->container['paResponse'];
    }

    /**
     * Sets paResponse
     *
     * @param string $paResponse Payment authorisation response returned by the card issuer. The `paResponse` field holds the PaRes value received from the card issuer.
     *
     * @return self
     */
    public function setPaResponse($paResponse)
    {
        $this->container['paResponse'] = $paResponse;

        return $this;
    }

    /**
     * Gets recurring
     *
     * @return \Adyen\Model\Payments\Recurring|null
     */
    public function getRecurring()
    {
        return $this->container['recurring'];
    }

    /**
     * Sets recurring
     *
     * @param \Adyen\Model\Payments\Recurring|null $recurring recurring
     *
     * @return self
     */
    public function setRecurring($recurring)
    {
        $this->container['recurring'] = $recurring;

        return $this;
    }

    /**
     * Gets recurringProcessingModel
     *
     * @return string|null
     */
    public function getRecurringProcessingModel()
    {
        return $this->container['recurringProcessingModel'];
    }

    /**
     * Sets recurringProcessingModel
     *
     * @param string|null $recurringProcessingModel Defines a recurring payment type. Required when creating a token to store payment details or using stored payment details. Allowed values: * `Subscription` – A transaction for a fixed or variable amount, which follows a fixed schedule. * `CardOnFile` – With a card-on-file (CoF) transaction, card details are stored to enable one-click or omnichannel journeys, or simply to streamline the checkout process. Any subscription not following a fixed schedule is also considered a card-on-file transaction. * `UnscheduledCardOnFile` – An unscheduled card-on-file (UCoF) transaction is a transaction that occurs on a non-fixed schedule and/or have variable amounts. For example, automatic top-ups when a cardholder's balance drops below a certain amount.
     *
     * @return self
     */
    public function setRecurringProcessingModel($recurringProcessingModel)
    {
        $allowedValues = $this->getRecurringProcessingModelAllowableValues();
        if (!in_array($recurringProcessingModel, $allowedValues, true)) {
            throw new \InvalidArgumentException(
                sprintf(
                    "Invalid value '%s' for 'recurringProcessingModel', must be one of '%s'",
                    $recurringProcessingModel,
                    implode("', '", $allowedValues)
                )
            );
        }
        $this->container['recurringProcessingModel'] = $recurringProcessingModel;

        return $this;
    }

    /**
     * Gets reference
     *
     * @return string|null
     */
    public function getReference()
    {
        return $this->container['reference'];
    }

    /**
     * Sets reference
     *
     * @param string|null $reference The reference to uniquely identify a payment. This reference is used in all communication with you about the payment status. We recommend using a unique value per payment; however, it is not a requirement. If you need to provide multiple references for a transaction, separate them with hyphens (\"-\"). Maximum length: 80 characters.
     *
     * @return self
     */
    public function setReference($reference)
    {
        $this->container['reference'] = $reference;

        return $this;
    }

    /**
     * Gets selectedBrand
     *
     * @return string|null
     */
    public function getSelectedBrand()
    {
        return $this->container['selectedBrand'];
    }

    /**
     * Sets selectedBrand
     *
     * @param string|null $selectedBrand Some payment methods require defining a value for this field to specify how to process the transaction.  For the Bancontact payment method, it can be set to: * `maestro` (default), to be processed like a Maestro card, or * `bcmc`, to be processed like a Bancontact card.
     *
     * @return self
     */
    public function setSelectedBrand($selectedBrand)
    {
        $this->container['selectedBrand'] = $selectedBrand;

        return $this;
    }

    /**
     * Gets selectedRecurringDetailReference
     *
     * @return string|null
     */
    public function getSelectedRecurringDetailReference()
    {
        return $this->container['selectedRecurringDetailReference'];
    }

    /**
     * Sets selectedRecurringDetailReference
     *
     * @param string|null $selectedRecurringDetailReference The `recurringDetailReference` you want to use for this payment. The value `LATEST` can be used to select the most recently stored recurring detail.
     *
     * @return self
     */
    public function setSelectedRecurringDetailReference($selectedRecurringDetailReference)
    {
        $this->container['selectedRecurringDetailReference'] = $selectedRecurringDetailReference;

        return $this;
    }

    /**
     * Gets sessionId
     *
     * @return string|null
     */
    public function getSessionId()
    {
        return $this->container['sessionId'];
    }

    /**
     * Sets sessionId
     *
     * @param string|null $sessionId A session ID used to identify a payment session.
     *
     * @return self
     */
    public function setSessionId($sessionId)
    {
        $this->container['sessionId'] = $sessionId;

        return $this;
    }

    /**
     * Gets shopperEmail
     *
     * @return string|null
     */
    public function getShopperEmail()
    {
        return $this->container['shopperEmail'];
    }

    /**
     * Sets shopperEmail
     *
     * @param string|null $shopperEmail The shopper's email address. We recommend that you provide this data, as it is used in velocity fraud checks. > For 3D Secure 2 transactions, schemes require `shopperEmail` for all browser-based and mobile implementations.
     *
     * @return self
     */
    public function setShopperEmail($shopperEmail)
    {
        $this->container['shopperEmail'] = $shopperEmail;

        return $this;
    }

    /**
     * Gets shopperIP
     *
     * @return string|null
     */
    public function getShopperIP()
    {
        return $this->container['shopperIP'];
    }

    /**
     * Sets shopperIP
     *
     * @param string|null $shopperIP The shopper's IP address. In general, we recommend that you provide this data, as it is used in a number of risk checks (for instance, number of payment attempts or location-based checks). > For 3D Secure 2 transactions, schemes require `shopperIP` for all browser-based implementations. This field is also mandatory for some merchants depending on your business model. For more information, [contact Support](https://www.adyen.help/hc/en-us/requests/new).
     *
     * @return self
     */
    public function setShopperIP($shopperIP)
    {
        $this->container['shopperIP'] = $shopperIP;

        return $this;
    }

    /**
     * Gets shopperInteraction
     *
     * @return string|null
     */
    public function getShopperInteraction()
    {
        return $this->container['shopperInteraction'];
    }

    /**
     * Sets shopperInteraction
     *
     * @param string|null $shopperInteraction Specifies the sales channel, through which the shopper gives their card details, and whether the shopper is a returning customer. For the web service API, Adyen assumes Ecommerce shopper interaction by default.  This field has the following possible values: * `Ecommerce` - Online transactions where the cardholder is present (online). For better authorisation rates, we recommend sending the card security code (CSC) along with the request. * `ContAuth` - Card on file and/or subscription transactions, where the cardholder is known to the merchant (returning customer). If the shopper is present (online), you can supply also the CSC to improve authorisation (one-click payment). * `Moto` - Mail-order and telephone-order transactions where the shopper is in contact with the merchant via email or telephone. * `POS` - Point-of-sale transactions where the shopper is physically present to make a payment using a secure payment terminal.
     *
     * @return self
     */
    public function setShopperInteraction($shopperInteraction)
    {
        $allowedValues = $this->getShopperInteractionAllowableValues();
        if (!in_array($shopperInteraction, $allowedValues, true)) {
            throw new \InvalidArgumentException(
                sprintf(
                    "Invalid value '%s' for 'shopperInteraction', must be one of '%s'",
                    $shopperInteraction,
                    implode("', '", $allowedValues)
                )
            );
        }
        $this->container['shopperInteraction'] = $shopperInteraction;

        return $this;
    }

    /**
     * Gets shopperLocale
     *
     * @return string|null
     */
    public function getShopperLocale()
    {
        return $this->container['shopperLocale'];
    }

    /**
     * Sets shopperLocale
     *
     * @param string|null $shopperLocale The combination of a language code and a country code to specify the language to be used in the payment.
     *
     * @return self
     */
    public function setShopperLocale($shopperLocale)
    {
        $this->container['shopperLocale'] = $shopperLocale;

        return $this;
    }

    /**
     * Gets shopperName
     *
     * @return \Adyen\Model\Payments\Name|null
     */
    public function getShopperName()
    {
        return $this->container['shopperName'];
    }

    /**
     * Sets shopperName
     *
     * @param \Adyen\Model\Payments\Name|null $shopperName shopperName
     *
     * @return self
     */
    public function setShopperName($shopperName)
    {
        $this->container['shopperName'] = $shopperName;

        return $this;
    }

    /**
     * Gets shopperReference
     *
     * @return string|null
     */
    public function getShopperReference()
    {
        return $this->container['shopperReference'];
    }

    /**
     * Sets shopperReference
     *
     * @param string|null $shopperReference Required for recurring payments.  Your reference to uniquely identify this shopper, for example user ID or account ID. The value is case-sensitive and must be at least three characters. > Your reference must not include personally identifiable information (PII) such as name or email address.
     *
     * @return self
     */
    public function setShopperReference($shopperReference)
    {
        $this->container['shopperReference'] = $shopperReference;

        return $this;
    }

    /**
     * Gets shopperStatement
     *
     * @return string|null
     */
    public function getShopperStatement()
    {
        return $this->container['shopperStatement'];
    }

    /**
     * Sets shopperStatement
     *
     * @param string|null $shopperStatement The text to be shown on the shopper's bank statement.  We recommend sending a maximum of 22 characters, otherwise banks might truncate the string.  Allowed characters: **a-z**, **A-Z**, **0-9**, spaces, and special characters **. , ' _ - ? + * /_**.
     *
     * @return self
     */
    public function setShopperStatement($shopperStatement)
    {
        $this->container['shopperStatement'] = $shopperStatement;

        return $this;
    }

    /**
     * Gets socialSecurityNumber
     *
     * @return string|null
     */
    public function getSocialSecurityNumber()
    {
        return $this->container['socialSecurityNumber'];
    }

    /**
     * Sets socialSecurityNumber
     *
     * @param string|null $socialSecurityNumber The shopper's social security number.
     *
     * @return self
     */
    public function setSocialSecurityNumber($socialSecurityNumber)
    {
        $this->container['socialSecurityNumber'] = $socialSecurityNumber;

        return $this;
    }

    /**
     * Gets splits
     *
     * @return \Adyen\Model\Payments\Split[]|null
     */
    public function getSplits()
    {
        return $this->container['splits'];
    }

    /**
     * Sets splits
     *
     * @param \Adyen\Model\Payments\Split[]|null $splits An array of objects specifying how the payment should be split when using either Adyen for Platforms for [marketplaces](https://docs.adyen.com/marketplaces/split-payments) or [platforms](https://docs.adyen.com/platforms/split-payments), or standalone [Issuing](https://docs.adyen.com/issuing/add-manage-funds#split).
     *
     * @return self
     */
    public function setSplits($splits)
    {
        $this->container['splits'] = $splits;

        return $this;
    }

    /**
     * Gets store
     *
     * @return string|null
     */
    public function getStore()
    {
        return $this->container['store'];
    }

    /**
     * Sets store
     *
     * @param string|null $store Required for Adyen for Platforms integrations if you are a platform model. This is your [reference](https://docs.adyen.com/api-explorer/Management/3/post/merchants/(merchantId)/stores#request-reference) (on [balance platform](https://docs.adyen.com/platforms)) or the [storeReference](https://docs.adyen.com/api-explorer/Account/latest/post/updateAccountHolder#request-accountHolderDetails-storeDetails-storeReference) (in the [classic integration](https://docs.adyen.com/classic-platforms/processing-payments/route-payment-to-store/#route-a-payment-to-a-store)) for the ecommerce or point-of-sale store that is processing the payment.
     *
     * @return self
     */
    public function setStore($store)
    {
        $this->container['store'] = $store;

        return $this;
    }

    /**
     * Gets telephoneNumber
     *
     * @return string|null
     */
    public function getTelephoneNumber()
    {
        return $this->container['telephoneNumber'];
    }

    /**
     * Sets telephoneNumber
     *
     * @param string|null $telephoneNumber The shopper's telephone number.
     *
     * @return self
     */
    public function setTelephoneNumber($telephoneNumber)
    {
        $this->container['telephoneNumber'] = $telephoneNumber;

        return $this;
    }

    /**
     * Gets threeDS2RequestData
     *
     * @return \Adyen\Model\Payments\ThreeDS2RequestData|null
     */
    public function getThreeDS2RequestData()
    {
        return $this->container['threeDS2RequestData'];
    }

    /**
     * Sets threeDS2RequestData
     *
     * @param \Adyen\Model\Payments\ThreeDS2RequestData|null $threeDS2RequestData threeDS2RequestData
     *
     * @return self
     */
    public function setThreeDS2RequestData($threeDS2RequestData)
    {
        $this->container['threeDS2RequestData'] = $threeDS2RequestData;

        return $this;
    }

    /**
     * Gets threeDSAuthenticationOnly
     *
     * @return bool|null
     */
    public function getThreeDSAuthenticationOnly()
    {
        return $this->container['threeDSAuthenticationOnly'];
    }

    /**
     * Sets threeDSAuthenticationOnly
     *
     * @param bool|null $threeDSAuthenticationOnly If set to true, you will only perform the [3D Secure 2 authentication](https://docs.adyen.com/online-payments/3d-secure/other-3ds-flows/authentication-only), and not the payment authorisation.
     *
     * @return self
     */
    public function setThreeDSAuthenticationOnly($threeDSAuthenticationOnly)
    {
        $this->container['threeDSAuthenticationOnly'] = $threeDSAuthenticationOnly;

        return $this;
    }

    /**
     * Gets totalsGroup
     *
     * @return string|null
     */
    public function getTotalsGroup()
    {
        return $this->container['totalsGroup'];
    }

    /**
     * Sets totalsGroup
     *
     * @param string|null $totalsGroup The reference value to aggregate sales totals in reporting. When not specified, the store field is used (if available).
     *
     * @return self
     */
    public function setTotalsGroup($totalsGroup)
    {
        $this->container['totalsGroup'] = $totalsGroup;

        return $this;
    }

    /**
     * Gets trustedShopper
     *
     * @return bool|null
     */
    public function getTrustedShopper()
    {
        return $this->container['trustedShopper'];
    }

    /**
     * Sets trustedShopper
     *
     * @param bool|null $trustedShopper Set to true if the payment should be routed to a trusted MID.
     *
     * @return self
     */
    public function setTrustedShopper($trustedShopper)
    {
        $this->container['trustedShopper'] = $trustedShopper;

        return $this;
    }
    /**
     * Returns true if offset exists. False otherwise.
     *
     * @param integer $offset Offset
     *
     * @return boolean
     */
    public function offsetExists($offset): bool
    {
        return isset($this->container[$offset]);
    }

    /**
     * Gets offset.
     *
     * @param integer $offset Offset
     *
     * @return mixed|null
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($offset)
    {
        return $this->container[$offset] ?? null;
    }

    /**
     * Sets value based on offset.
     *
     * @param int|null $offset Offset
     * @param mixed    $value  Value to be set
     *
     * @return void
     */
    public function offsetSet($offset, $value): void
    {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    /**
     * Unsets offset.
     *
     * @param integer $offset Offset
     *
     * @return void
     */
    public function offsetUnset($offset): void
    {
        unset($this->container[$offset]);
    }

    /**
     * Serializes the object to a value that can be serialized natively by json_encode().
     * @link https://www.php.net/manual/en/jsonserializable.jsonserialize.php
     *
     * @return mixed Returns data which can be serialized by json_encode(), which is a value
     * of any type other than a resource.
     */
    #[\ReturnTypeWillChange]
    public function jsonSerialize()
    {
        return ObjectSerializer::sanitizeForSerialization($this);
    }

    public function toArray(): array
    {
        $array = [];
        foreach (self::$openAPITypes as $propertyName => $propertyType) {
            $propertyValue = $this[$propertyName];
            if ($propertyValue !== null) {
                // Check if the property value is an object and has a toArray() method
                if (is_object($propertyValue) && method_exists($propertyValue, 'toArray')) {
                    $array[$propertyName] = $propertyValue->toArray();
                // Check if it's type datetime
                } elseif ($propertyValue instanceof \DateTime) {
                    $array[$propertyName] = $propertyValue->format(DATE_ATOM);
                // If it's an array type we should check whether it contains objects and if so call toArray method
                } elseif (is_array($propertyValue)) {
                    $array[$propertyName] = array_map(function ($item) {
                        return $item instanceof ModelInterface ? $item->toArray() : $item;
                    }, $propertyValue);
                } else {
                    // Otherwise, directly assign the property value to the array
                    $array[$propertyName] = $propertyValue;
                }
            }
        }
        return $array;
    }

    /**
     * Gets the string presentation of the object
     *
     * @return string
     */
    public function __toString()
    {
        return json_encode(
            ObjectSerializer::sanitizeForSerialization($this),
            JSON_PRETTY_PRINT
        );
    }
}
