<?php
/**
 * OrderTaxesBase
 *
 * PHP version 8.1
 *
 * @category Class
 * @package  Bigcommerce\OrdersV2
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 */

/**
 * Orders V2
 *
 * Manage order coupons, messages, products, shipping addresses, statuses, taxes, shipments, and shipping address quotes.  - [Authentication](#authentication) - [Order](#order)  ## Authentication  Authenticate requests by including an [OAuth](https://developer.bigcommerce.com/api-docs/getting-started/authentication) `access_token` request header.  ```http GET https://api.bigcommerce.com/stores/{{STORE_HASH}}/v3/{{ENDPOINT}} Content-Type: application/json X-Auth-Token: {{ACCESS_TOKEN}} ```  ### OAuth Scopes  |  **UI Name** | **Permission** | **Parameter** | | --- | --- | --- | |  Orders | modify | `store_v2_orders` | |  Orders | read-only | `store_v2_orders_read_only` |   ## Order  The Order object contains a record of the purchase agreement between a shopper and a merchant. To learn more about creating orders, see [Orders API Guide](/api-docs/orders/orders-api-overview).  ### Currency Fields  The **default** currency refers to the transactional currency which is the currency the shopper pays in.  The **display** currency refers to the presentational currency used to present prices to the shopper on the storefront.  * `currency_id` - the display currency ID. Depending on the currency selected, the value may be different from the transactional currency. * `currency_code` - the currency code of the display currency used to present prices to the shopper on the storefront. Depending on the currency selected, the value may be different from the transactional currency. * `currency_exchange_rate` - the exchange rate between the store's default currency and the display currency. For orders created using the V2 endpoints, this value is always 1 (only in the storefront this value can be different to 1). * `default_currency_id` - the transactional currency ID. * `default_currency_code` - the currency code of the transactional currency the shopper pays in.  The following additional fields are returned on orders when Multi-Currency is enabled on the store:  * `store_default_currency_code` - the currency code of the store's default currency. * `store_default_to_transactional_exchange_rate` - the exchange rate between the store's default currency and the transactional currency used in the order.  **Example:**  ```json {   ...   \"currency_id\": 4,   \"currency_code\": \"EUR\",   \"currency_exchange_rate\": 1,   \"default_currency_id\": 4,   \"default_currency_code\": \"EUR\",   \"store_default_currency_code\": \"USD\",   \"store_default_to_transactional_exchange_rate\": \"100.0000000000\"   ... } ```
 *
 * The version of the OpenAPI document: 
 * Generated by: https://openapi-generator.tech
 * Generator version: 7.13.0
 */

/**
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

namespace Bigcommerce\OrdersV2\Model;

use \ArrayAccess;
use \Bigcommerce\OrdersV2\ObjectSerializer;

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

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

    /**
      * Array of property to type mappings. Used for (de)serialization
      *
      * @var string[]
      */
    protected static $openAPITypes = [
        'id' => 'int',
        'order_id' => 'int',
        'order_address_id' => 'int',
        'tax_rate_id' => 'int',
        'tax_class_id' => 'int',
        'name' => 'string',
        'class' => 'string',
        'rate' => 'string',
        'priority' => 'float',
        'priority_amount' => 'string',
        'line_amount' => 'string',
        'order_product_id' => 'string',
        'line_item_type' => 'string'
    ];

    /**
      * 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 = [
        'id' => null,
        'order_id' => null,
        'order_address_id' => null,
        'tax_rate_id' => null,
        'tax_class_id' => null,
        'name' => null,
        'class' => null,
        'rate' => null,
        'priority' => null,
        'priority_amount' => null,
        'line_amount' => null,
        'order_product_id' => null,
        'line_item_type' => null
    ];

    /**
      * Array of nullable properties. Used for (de)serialization
      *
      * @var boolean[]
      */
    protected static array $openAPINullables = [
        'id' => false,
        'order_id' => false,
        'order_address_id' => false,
        'tax_rate_id' => false,
        'tax_class_id' => false,
        'name' => false,
        'class' => false,
        'rate' => false,
        'priority' => false,
        'priority_amount' => false,
        'line_amount' => false,
        'order_product_id' => false,
        'line_item_type' => false
    ];

    /**
      * If a nullable field gets set to null, insert it here
      *
      * @var boolean[]
      */
    protected array $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 = [
        'id' => 'id',
        'order_id' => 'order_id',
        'order_address_id' => 'order_address_id',
        'tax_rate_id' => 'tax_rate_id',
        'tax_class_id' => 'tax_class_id',
        'name' => 'name',
        'class' => 'class',
        'rate' => 'rate',
        'priority' => 'priority',
        'priority_amount' => 'priority_amount',
        'line_amount' => 'line_amount',
        'order_product_id' => 'order_product_id',
        'line_item_type' => 'line_item_type'
    ];

    /**
     * Array of attributes to setter functions (for deserialization of responses)
     *
     * @var string[]
     */
    protected static $setters = [
        'id' => 'setId',
        'order_id' => 'setOrderId',
        'order_address_id' => 'setOrderAddressId',
        'tax_rate_id' => 'setTaxRateId',
        'tax_class_id' => 'setTaxClassId',
        'name' => 'setName',
        'class' => 'setClass',
        'rate' => 'setRate',
        'priority' => 'setPriority',
        'priority_amount' => 'setPriorityAmount',
        'line_amount' => 'setLineAmount',
        'order_product_id' => 'setOrderProductId',
        'line_item_type' => 'setLineItemType'
    ];

    /**
     * Array of attributes to getter functions (for serialization of requests)
     *
     * @var string[]
     */
    protected static $getters = [
        'id' => 'getId',
        'order_id' => 'getOrderId',
        'order_address_id' => 'getOrderAddressId',
        'tax_rate_id' => 'getTaxRateId',
        'tax_class_id' => 'getTaxClassId',
        'name' => 'getName',
        'class' => 'getClass',
        'rate' => 'getRate',
        'priority' => 'getPriority',
        'priority_amount' => 'getPriorityAmount',
        'line_amount' => 'getLineAmount',
        'order_product_id' => 'getOrderProductId',
        'line_item_type' => 'getLineItemType'
    ];

    /**
     * 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 LINE_ITEM_TYPE_PRODUCT = 'product';
    public const LINE_ITEM_TYPE_ITEM = 'item';
    public const LINE_ITEM_TYPE_SHIPPING = 'shipping';
    public const LINE_ITEM_TYPE_HANDLING = 'handling';
    public const LINE_ITEM_TYPE_GIFT_WRAPPING = 'gift-wrapping';

    /**
     * Gets allowable values of the enum
     *
     * @return string[]
     */
    public function getLineItemTypeAllowableValues()
    {
        return [
            self::LINE_ITEM_TYPE_PRODUCT,
            self::LINE_ITEM_TYPE_ITEM,
            self::LINE_ITEM_TYPE_SHIPPING,
            self::LINE_ITEM_TYPE_HANDLING,
            self::LINE_ITEM_TYPE_GIFT_WRAPPING,
        ];
    }

    /**
     * Associative array for storing property values
     *
     * @var mixed[]
     */
    protected $container = [];

    /**
     * Constructor
     *
     * @param mixed[]|null $data Associated array of property values
     *                      initializing the model
     */
    public function __construct(?array $data = null)
    {
        $this->setIfExists('id', $data ?? [], null);
        $this->setIfExists('order_id', $data ?? [], null);
        $this->setIfExists('order_address_id', $data ?? [], null);
        $this->setIfExists('tax_rate_id', $data ?? [], null);
        $this->setIfExists('tax_class_id', $data ?? [], null);
        $this->setIfExists('name', $data ?? [], null);
        $this->setIfExists('class', $data ?? [], null);
        $this->setIfExists('rate', $data ?? [], null);
        $this->setIfExists('priority', $data ?? [], null);
        $this->setIfExists('priority_amount', $data ?? [], null);
        $this->setIfExists('line_amount', $data ?? [], null);
        $this->setIfExists('order_product_id', $data ?? [], null);
        $this->setIfExists('line_item_type', $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 = [];

        $allowedValues = $this->getLineItemTypeAllowableValues();
        if (!is_null($this->container['line_item_type']) && !in_array($this->container['line_item_type'], $allowedValues, true)) {
            $invalidProperties[] = sprintf(
                "invalid value '%s' for 'line_item_type', must be one of '%s'",
                $this->container['line_item_type'],
                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 id
     *
     * @return int|null
     */
    public function getId()
    {
        return $this->container['id'];
    }

    /**
     * Sets id
     *
     * @param int|null $id The unique numeric identifier of the taxes object.
     *
     * @return self
     */
    public function setId($id)
    {
        if (is_null($id)) {
            throw new \InvalidArgumentException('non-nullable id cannot be null');
        }
        $this->container['id'] = $id;

        return $this;
    }

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

    /**
     * Sets order_id
     *
     * @param int|null $order_id The unique numeric identifier of the order to which the tax was applied. NOTE: Not included if the store was using the automatic tax feature.
     *
     * @return self
     */
    public function setOrderId($order_id)
    {
        if (is_null($order_id)) {
            throw new \InvalidArgumentException('non-nullable order_id cannot be null');
        }
        $this->container['order_id'] = $order_id;

        return $this;
    }

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

    /**
     * Sets order_address_id
     *
     * @param int|null $order_address_id The unique numeric identifier of the order address object associated with the order. NOTE: Not included if the store was using the automatic tax feature.
     *
     * @return self
     */
    public function setOrderAddressId($order_address_id)
    {
        if (is_null($order_address_id)) {
            throw new \InvalidArgumentException('non-nullable order_address_id cannot be null');
        }
        $this->container['order_address_id'] = $order_address_id;

        return $this;
    }

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

    /**
     * Sets tax_rate_id
     *
     * @param int|null $tax_rate_id The unique numeric identifier of the tax rate.
     *
     * @return self
     */
    public function setTaxRateId($tax_rate_id)
    {
        if (is_null($tax_rate_id)) {
            throw new \InvalidArgumentException('non-nullable tax_rate_id cannot be null');
        }
        $this->container['tax_rate_id'] = $tax_rate_id;

        return $this;
    }

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

    /**
     * Sets tax_class_id
     *
     * @param int|null $tax_class_id The unique numeric identifier of the tax class object. NOTE: Will be 0 if automatic tax was enabled, or if the default tax class was used.
     *
     * @return self
     */
    public function setTaxClassId($tax_class_id)
    {
        if (is_null($tax_class_id)) {
            throw new \InvalidArgumentException('non-nullable tax_class_id cannot be null');
        }
        $this->container['tax_class_id'] = $tax_class_id;

        return $this;
    }

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

    /**
     * Sets name
     *
     * @param string|null $name The name of the tax class object.
     *
     * @return self
     */
    public function setName($name)
    {
        if (is_null($name)) {
            throw new \InvalidArgumentException('non-nullable name cannot be null');
        }
        $this->container['name'] = $name;

        return $this;
    }

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

    /**
     * Sets class
     *
     * @param string|null $class The name of the type of tax that was applied. NOTE: will be 'Automatic Tax' if automatic tax was enabled.
     *
     * @return self
     */
    public function setClass($class)
    {
        if (is_null($class)) {
            throw new \InvalidArgumentException('non-nullable class cannot be null');
        }
        $this->container['class'] = $class;

        return $this;
    }

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

    /**
     * Sets rate
     *
     * @param string|null $rate The tax rate.  The priority order in which the tax is applied (Float, Float-As-String, Integer)
     *
     * @return self
     */
    public function setRate($rate)
    {
        if (is_null($rate)) {
            throw new \InvalidArgumentException('non-nullable rate cannot be null');
        }
        $this->container['rate'] = $rate;

        return $this;
    }

    /**
     * Gets priority
     *
     * @return float|null
     */
    public function getPriority()
    {
        return $this->container['priority'];
    }

    /**
     * Sets priority
     *
     * @param float|null $priority The order in which the tax is applied
     *
     * @return self
     */
    public function setPriority($priority)
    {
        if (is_null($priority)) {
            throw new \InvalidArgumentException('non-nullable priority cannot be null');
        }
        $this->container['priority'] = $priority;

        return $this;
    }

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

    /**
     * Sets priority_amount
     *
     * @param string|null $priority_amount The amount of tax calculated on the order.   (Float, Float-As-String, Integer)
     *
     * @return self
     */
    public function setPriorityAmount($priority_amount)
    {
        if (is_null($priority_amount)) {
            throw new \InvalidArgumentException('non-nullable priority_amount cannot be null');
        }
        $this->container['priority_amount'] = $priority_amount;

        return $this;
    }

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

    /**
     * Sets line_amount
     *
     * @param string|null $line_amount (Float, Float-As-String, Integer)
     *
     * @return self
     */
    public function setLineAmount($line_amount)
    {
        if (is_null($line_amount)) {
            throw new \InvalidArgumentException('non-nullable line_amount cannot be null');
        }
        $this->container['line_amount'] = $line_amount;

        return $this;
    }

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

    /**
     * Sets order_product_id
     *
     * @param string|null $order_product_id If the `line_item_type` is `item` or `handling` then this field will be the order product id. Otherwise the field will return as null.
     *
     * @return self
     */
    public function setOrderProductId($order_product_id)
    {
        if (is_null($order_product_id)) {
            throw new \InvalidArgumentException('non-nullable order_product_id cannot be null');
        }
        $this->container['order_product_id'] = $order_product_id;

        return $this;
    }

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

    /**
     * Sets line_item_type
     *
     * @param string|null $line_item_type Type of tax on item
     *
     * @return self
     */
    public function setLineItemType($line_item_type)
    {
        if (is_null($line_item_type)) {
            throw new \InvalidArgumentException('non-nullable line_item_type cannot be null');
        }
        $allowedValues = $this->getLineItemTypeAllowableValues();
        if (!in_array($line_item_type, $allowedValues, true)) {
            throw new \InvalidArgumentException(
                sprintf(
                    "Invalid value '%s' for 'line_item_type', must be one of '%s'",
                    $line_item_type,
                    implode("', '", $allowedValues)
                )
            );
        }
        $this->container['line_item_type'] = $line_item_type;

        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);
    }

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

    /**
     * Gets a header-safe presentation of the object
     *
     * @return string
     */
    public function toHeaderValue()
    {
        return json_encode(ObjectSerializer::sanitizeForSerialization($this));
    }
}


