<?php
/**
 * ProductListItem
 *
 * PHP version 7.3
 *
 * @category Class
 * @package  Pipedrive
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 */

/**
 * Pipedrive API v1
 *
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 *
 * The version of the OpenAPI document: 1.0.0
 * Generated by: https://openapi-generator.tech
 * OpenAPI Generator version: 5.3.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 Pipedrive\Model;

use ArrayAccess;
use JsonException;
use JsonSerializable;
use Pipedrive\Traits\RawData;
use Pipedrive\ObjectSerializer;

/**
 * ProductListItem Class Doc Comment
 *
 * @category Class
 * @package  Pipedrive
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 * @implements ArrayAccess<TKey, TValue>
 * @template TKey int|null
 * @template TValue mixed|null
 */
class ProductListItem implements ModelInterface, ArrayAccess, JsonSerializable
{
    use RawData;

    public const DISCRIMINATOR = null;

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

    /**
      * Array of property to type mappings. Used for (de)serialization
      *
      * @var string[]
      * @phpstan-var array<string, string>
      * @phpsalm-var array<string, string>
      */
    protected static array $openAPITypes = [
        'id' => 'int',
        'deal_id' => 'int',
        'order_nr' => 'int',
        'product_id' => 'int',
        'product_variation_id' => 'int',
        'item_price' => 'int',
        'discount' => 'float',
        'discount_type' => 'string',
        'sum' => 'float',
        'currency' => 'string',
        'enabled_flag' => 'bool',
        'add_time' => 'string',
        'last_edit' => 'string',
        'comments' => 'string',
        'active_flag' => 'bool',
        'tax' => 'float',
        'tax_method' => 'string',
        'name' => 'string',
        'sum_formatted' => 'string',
        'quantity_formatted' => 'string',
        'quantity' => 'int',
        'product' => '\Pipedrive\Model\ProductWithArrayPrices'
    ];

    /**
      * 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,
        'deal_id' => null,
        'order_nr' => null,
        'product_id' => null,
        'product_variation_id' => null,
        'item_price' => null,
        'discount' => null,
        'discount_type' => null,
        'sum' => null,
        'currency' => null,
        'enabled_flag' => null,
        'add_time' => null,
        'last_edit' => null,
        'comments' => null,
        'active_flag' => null,
        'tax' => null,
        'tax_method' => null,
        'name' => null,
        'sum_formatted' => null,
        'quantity_formatted' => null,
        'quantity' => null,
        'product' => null
    ];

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

    /**
     * Array of property to format mappings. Used for (de)serialization
     *
     * @phpstan-return array<string, string|null>
     * @psalm-return array<string, string|null>
     * @return array
     */
    public static function openAPIFormats(): array
    {
        return self::$openAPIFormats;
    }

    /**
     * Array of attributes where the key is the local name,
     * and the value is the original name
     *
     * @var string[]
     */
    protected static $attributeMap = [
        'id' => 'id',
        'deal_id' => 'deal_id',
        'order_nr' => 'order_nr',
        'product_id' => 'product_id',
        'product_variation_id' => 'product_variation_id',
        'item_price' => 'item_price',
        'discount' => 'discount',
        'discount_type' => 'discount_type',
        'sum' => 'sum',
        'currency' => 'currency',
        'enabled_flag' => 'enabled_flag',
        'add_time' => 'add_time',
        'last_edit' => 'last_edit',
        'comments' => 'comments',
        'active_flag' => 'active_flag',
        'tax' => 'tax',
        'tax_method' => 'tax_method',
        'name' => 'name',
        'sum_formatted' => 'sum_formatted',
        'quantity_formatted' => 'quantity_formatted',
        'quantity' => 'quantity',
        'product' => 'product'
    ];

    /**
     * Array of attributes to setter functions (for deserialization of responses)
     *
     * @var string[]
     */
    protected static $setters = [
        'id' => 'setId',
        'deal_id' => 'setDealId',
        'order_nr' => 'setOrderNr',
        'product_id' => 'setProductId',
        'product_variation_id' => 'setProductVariationId',
        'item_price' => 'setItemPrice',
        'discount' => 'setDiscount',
        'discount_type' => 'setDiscountType',
        'sum' => 'setSum',
        'currency' => 'setCurrency',
        'enabled_flag' => 'setEnabledFlag',
        'add_time' => 'setAddTime',
        'last_edit' => 'setLastEdit',
        'comments' => 'setComments',
        'active_flag' => 'setActiveFlag',
        'tax' => 'setTax',
        'tax_method' => 'setTaxMethod',
        'name' => 'setName',
        'sum_formatted' => 'setSumFormatted',
        'quantity_formatted' => 'setQuantityFormatted',
        'quantity' => 'setQuantity',
        'product' => 'setProduct'
    ];

    /**
     * Array of attributes to getter functions (for serialization of requests)
     *
     * @var string[]
     */
    protected static $getters = [
        'id' => 'getId',
        'deal_id' => 'getDealId',
        'order_nr' => 'getOrderNr',
        'product_id' => 'getProductId',
        'product_variation_id' => 'getProductVariationId',
        'item_price' => 'getItemPrice',
        'discount' => 'getDiscount',
        'discount_type' => 'getDiscountType',
        'sum' => 'getSum',
        'currency' => 'getCurrency',
        'enabled_flag' => 'getEnabledFlag',
        'add_time' => 'getAddTime',
        'last_edit' => 'getLastEdit',
        'comments' => 'getComments',
        'active_flag' => 'getActiveFlag',
        'tax' => 'getTax',
        'tax_method' => 'getTaxMethod',
        'name' => 'getName',
        'sum_formatted' => 'getSumFormatted',
        'quantity_formatted' => 'getQuantityFormatted',
        'quantity' => 'getQuantity',
        'product' => 'getProduct'
    ];

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

    /**
     * Array of attributes to setter functions (for deserialization of responses)
     *
     * @phpstan-return array<string, string>
     * @psalm-return array<string, string>
     * @return array
     */
    public static function setters(): array
    {
        return self::$setters;
    }

    /**
     * Array of attributes to getter functions (for serialization of requests)
     *
     * @phpstan-return array<string, string>
     * @psalm-return array<string, string>
     * @return array
     */
    public static function getters(): array
    {
        return self::$getters;
    }

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

    const DISCOUNT_TYPE_PERCENTAGE = 'percentage';
    const DISCOUNT_TYPE_AMOUNT = 'amount';
    const TAX_METHOD_EXCLUSIVE = 'exclusive';
    const TAX_METHOD_INCLUSIVE = 'inclusive';
    const TAX_METHOD_NONE = 'none';

    /**
     * Gets allowable values of the enum
     *
     * @phpstan-return  array<string|int>
     * @phpsalm-return  array<string|int>
     * @return (string|int)[]
     */
    public function getDiscountTypeAllowableValues(): array
    {
        return [
            self::DISCOUNT_TYPE_PERCENTAGE,
            self::DISCOUNT_TYPE_AMOUNT,
        ];
    }

    /**
     * Gets allowable values of the enum
     *
     * @phpstan-return  array<string|int>
     * @phpsalm-return  array<string|int>
     * @return (string|int)[]
     */
    public function getTaxMethodAllowableValues(): array
    {
        return [
            self::TAX_METHOD_EXCLUSIVE,
            self::TAX_METHOD_INCLUSIVE,
            self::TAX_METHOD_NONE,
        ];
    }

    /**
     * Associative array for storing property values
     *
     * @var array
     * @phpstan-var array<int|string, mixed>
     * @psalm-var array<int|string, mixed>
     */
    protected array $container = [];

    /**
     * Constructor
     *
     * @phpstan-param array<string, mixed>|null $data
     * @psalm-param array<string, mixed>|null $data
     * @param array|null $data Associated array of property values
     *                      initializing the model
     */
    public function __construct(array $data = null)
    {
        $this->container['id'] = $data['id'] ?? null;
        $this->container['deal_id'] = $data['deal_id'] ?? null;
        $this->container['order_nr'] = $data['order_nr'] ?? null;
        $this->container['product_id'] = $data['product_id'] ?? null;
        $this->container['product_variation_id'] = $data['product_variation_id'] ?? null;
        $this->container['item_price'] = $data['item_price'] ?? null;
        $this->container['discount'] = $data['discount'] ?? 0;
        $this->container['discount_type'] = $data['discount_type'] ?? 'percentage';
        $this->container['sum'] = $data['sum'] ?? null;
        $this->container['currency'] = $data['currency'] ?? null;
        $this->container['enabled_flag'] = $data['enabled_flag'] ?? null;
        $this->container['add_time'] = $data['add_time'] ?? null;
        $this->container['last_edit'] = $data['last_edit'] ?? null;
        $this->container['comments'] = $data['comments'] ?? null;
        $this->container['active_flag'] = $data['active_flag'] ?? null;
        $this->container['tax'] = $data['tax'] ?? null;
        $this->container['tax_method'] = $data['tax_method'] ?? null;
        $this->container['name'] = $data['name'] ?? null;
        $this->container['sum_formatted'] = $data['sum_formatted'] ?? null;
        $this->container['quantity_formatted'] = $data['quantity_formatted'] ?? null;
        $this->container['quantity'] = $data['quantity'] ?? null;
        $this->container['product'] = $data['product'] ?? null;
    }

    /**
     * Show all the invalid properties with reasons.
     *
     * @return array invalid properties with reasons
     * @phpstan-return array<int, string>
     * @psalm-return array<int, string>
     */
    public function listInvalidProperties(): array
    {
        $invalidProperties = [];

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

        $allowedValues = $this->getTaxMethodAllowableValues();
        if (!is_null($this->container['tax_method']) && !in_array($this->container['tax_method'], $allowedValues, true)) {
            $invalidProperties[] = sprintf(
                "invalid value '%s' for 'tax_method', must be one of '%s'",
                $this->container['tax_method'],
                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(): bool
    {
        return count($this->listInvalidProperties()) === 0;
    }


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

    /**
     * Sets id
     *
     * @param int|null $id The ID of the deal-product (the ID of the product attached to the deal)
     *
     * @return self
     */
    public function setId($id): self
    {
        $this->container['id'] = $id;

        return $this;
    }

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

    /**
     * Sets deal_id
     *
     * @param int|null $deal_id The ID of the deal
     *
     * @return self
     */
    public function setDealId($deal_id): self
    {
        $this->container['deal_id'] = $deal_id;

        return $this;
    }

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

    /**
     * Sets order_nr
     *
     * @param int|null $order_nr The order number of the product
     *
     * @return self
     */
    public function setOrderNr($order_nr): self
    {
        $this->container['order_nr'] = $order_nr;

        return $this;
    }

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

    /**
     * Sets product_id
     *
     * @param int|null $product_id The ID of the product
     *
     * @return self
     */
    public function setProductId($product_id): self
    {
        $this->container['product_id'] = $product_id;

        return $this;
    }

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

    /**
     * Sets product_variation_id
     *
     * @param int|null $product_variation_id The ID of the product variation
     *
     * @return self
     */
    public function setProductVariationId($product_variation_id): self
    {
        $this->container['product_variation_id'] = $product_variation_id;

        return $this;
    }

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

    /**
     * Sets item_price
     *
     * @param int|null $item_price The price value of the product
     *
     * @return self
     */
    public function setItemPrice($item_price): self
    {
        $this->container['item_price'] = $item_price;

        return $this;
    }

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

    /**
     * Sets discount
     *
     * @param float|null $discount The value of the discount. The `discount_type` field can be used to specify whether the value is an amount or a percentage
     *
     * @return self
     */
    public function setDiscount($discount): self
    {
        $this->container['discount'] = $discount;

        return $this;
    }

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

    /**
     * Sets discount_type
     *
     * @param string|null $discount_type The type of the discount's value
     *
     * @return self
     */
    public function setDiscountType($discount_type): self
    {
        $allowedValues = $this->getDiscountTypeAllowableValues();
        if (!is_null($discount_type) && !in_array($discount_type, $allowedValues, true)) {
            throw new \InvalidArgumentException(
                sprintf(
                    "Invalid value '%s' for 'discount_type', must be one of '%s'",
                    $discount_type,
                    implode("', '", $allowedValues)
                )
            );
        }
        $this->container['discount_type'] = $discount_type;

        return $this;
    }

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

    /**
     * Sets sum
     *
     * @param float|null $sum The sum of all the products attached to the deal
     *
     * @return self
     */
    public function setSum($sum): self
    {
        $this->container['sum'] = $sum;

        return $this;
    }

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

    /**
     * Sets currency
     *
     * @param string|null $currency The currency associated with the deal product
     *
     * @return self
     */
    public function setCurrency($currency): self
    {
        $this->container['currency'] = $currency;

        return $this;
    }

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

    /**
     * Sets enabled_flag
     *
     * @param bool|null $enabled_flag Whether the product is enabled or not
     *
     * @return self
     */
    public function setEnabledFlag($enabled_flag): self
    {
        $this->container['enabled_flag'] = $enabled_flag;

        return $this;
    }

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

    /**
     * Sets add_time
     *
     * @param string|null $add_time The date and time when the product was added to the deal
     *
     * @return self
     */
    public function setAddTime($add_time): self
    {
        $this->container['add_time'] = $add_time;

        return $this;
    }

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

    /**
     * Sets last_edit
     *
     * @param string|null $last_edit The date and time when the deal product was last edited
     *
     * @return self
     */
    public function setLastEdit($last_edit): self
    {
        $this->container['last_edit'] = $last_edit;

        return $this;
    }

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

    /**
     * Sets comments
     *
     * @param string|null $comments The comments of the product
     *
     * @return self
     */
    public function setComments($comments): self
    {
        $this->container['comments'] = $comments;

        return $this;
    }

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

    /**
     * Sets active_flag
     *
     * @param bool|null $active_flag Whether the product is active or not
     *
     * @return self
     */
    public function setActiveFlag($active_flag): self
    {
        $this->container['active_flag'] = $active_flag;

        return $this;
    }

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

    /**
     * Sets tax
     *
     * @param float|null $tax The product tax
     *
     * @return self
     */
    public function setTax($tax): self
    {
        $this->container['tax'] = $tax;

        return $this;
    }

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

    /**
     * Sets tax_method
     *
     * @param string|null $tax_method The tax option to be applied to the products. When using `inclusive`, the tax percentage will already be included in the price. When using `exclusive`, the tax will not be included in the price. When using `none`, no tax will be added. Use the `tax` field for defining the tax percentage amount. By default, the user setting value for tax options will be used. Changing this in one product affects the rest of the products attached to the deal
     *
     * @return self
     */
    public function setTaxMethod($tax_method): self
    {
        $allowedValues = $this->getTaxMethodAllowableValues();
        if (!is_null($tax_method) && !in_array($tax_method, $allowedValues, true)) {
            throw new \InvalidArgumentException(
                sprintf(
                    "Invalid value '%s' for 'tax_method', must be one of '%s'",
                    $tax_method,
                    implode("', '", $allowedValues)
                )
            );
        }
        $this->container['tax_method'] = $tax_method;

        return $this;
    }

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

    /**
     * Sets name
     *
     * @param string|null $name The product name
     *
     * @return self
     */
    public function setName($name): self
    {
        $this->container['name'] = $name;

        return $this;
    }

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

    /**
     * Sets sum_formatted
     *
     * @param string|null $sum_formatted The formatted sum of the product
     *
     * @return self
     */
    public function setSumFormatted($sum_formatted): self
    {
        $this->container['sum_formatted'] = $sum_formatted;

        return $this;
    }

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

    /**
     * Sets quantity_formatted
     *
     * @param string|null $quantity_formatted The formatted quantity of the product
     *
     * @return self
     */
    public function setQuantityFormatted($quantity_formatted): self
    {
        $this->container['quantity_formatted'] = $quantity_formatted;

        return $this;
    }

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

    /**
     * Sets quantity
     *
     * @param int|null $quantity The quantity of the product
     *
     * @return self
     */
    public function setQuantity($quantity): self
    {
        $this->container['quantity'] = $quantity;

        return $this;
    }

    /**
     * Gets product
     *
     * @return \Pipedrive\Model\ProductWithArrayPrices|null
     */
    public function getProduct()
    {
        return $this->container['product'];
    }

    /**
     * Sets product
     *
     * @param \Pipedrive\Model\ProductWithArrayPrices|null $product product
     *
     * @return self
     */
    public function setProduct($product): self
    {
        $this->container['product'] = $product;

        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
     */
    public function offsetGet($offset): mixed
    {
        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.
     */
    public function jsonSerialize(): mixed
    {
       return ObjectSerializer::sanitizeForSerialization($this);
    }

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

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


