<?php

declare(strict_types=1);

namespace EDD\Vendor\Square\Models;

use stdClass;

/**
 * Represents a change in state or quantity of product inventory at a
 * particular time and location.
 */
class InventoryAdjustment implements \JsonSerializable
{
    /**
     * @var string|null
     */
    private $id;

    /**
     * @var array
     */
    private $referenceId = [];

    /**
     * @var string|null
     */
    private $fromState;

    /**
     * @var string|null
     */
    private $toState;

    /**
     * @var array
     */
    private $locationId = [];

    /**
     * @var array
     */
    private $catalogObjectId = [];

    /**
     * @var array
     */
    private $catalogObjectType = [];

    /**
     * @var array
     */
    private $quantity = [];

    /**
     * @var Money|null
     */
    private $totalPriceMoney;

    /**
     * @var array
     */
    private $occurredAt = [];

    /**
     * @var string|null
     */
    private $createdAt;

    /**
     * @var SourceApplication|null
     */
    private $source;

    /**
     * @var array
     */
    private $employeeId = [];

    /**
     * @var array
     */
    private $teamMemberId = [];

    /**
     * @var string|null
     */
    private $transactionId;

    /**
     * @var string|null
     */
    private $refundId;

    /**
     * @var string|null
     */
    private $purchaseOrderId;

    /**
     * @var string|null
     */
    private $goodsReceiptId;

    /**
     * @var InventoryAdjustmentGroup|null
     */
    private $adjustmentGroup;

    /**
     * Returns Id.
     * A unique ID generated by EDD\Vendor\Square for the
     * `InventoryAdjustment`.
     */
    public function getId(): ?string
    {
        return $this->id;
    }

    /**
     * Sets Id.
     * A unique ID generated by EDD\Vendor\Square for the
     * `InventoryAdjustment`.
     *
     * @maps id
     */
    public function setId(?string $id): void
    {
        $this->id = $id;
    }

    /**
     * Returns Reference Id.
     * An optional ID provided by the application to tie the
     * `InventoryAdjustment` to an external
     * system.
     */
    public function getReferenceId(): ?string
    {
        if (count($this->referenceId) == 0) {
            return null;
        }
        return $this->referenceId['value'];
    }

    /**
     * Sets Reference Id.
     * An optional ID provided by the application to tie the
     * `InventoryAdjustment` to an external
     * system.
     *
     * @maps reference_id
     */
    public function setReferenceId(?string $referenceId): void
    {
        $this->referenceId['value'] = $referenceId;
    }

    /**
     * Unsets Reference Id.
     * An optional ID provided by the application to tie the
     * `InventoryAdjustment` to an external
     * system.
     */
    public function unsetReferenceId(): void
    {
        $this->referenceId = [];
    }

    /**
     * Returns From State.
     * Indicates the state of a tracked item quantity in the lifecycle of goods.
     */
    public function getFromState(): ?string
    {
        return $this->fromState;
    }

    /**
     * Sets From State.
     * Indicates the state of a tracked item quantity in the lifecycle of goods.
     *
     * @maps from_state
     */
    public function setFromState(?string $fromState): void
    {
        $this->fromState = $fromState;
    }

    /**
     * Returns To State.
     * Indicates the state of a tracked item quantity in the lifecycle of goods.
     */
    public function getToState(): ?string
    {
        return $this->toState;
    }

    /**
     * Sets To State.
     * Indicates the state of a tracked item quantity in the lifecycle of goods.
     *
     * @maps to_state
     */
    public function setToState(?string $toState): void
    {
        $this->toState = $toState;
    }

    /**
     * Returns Location Id.
     * The Square-generated ID of the [Location](entity:Location) where the related
     * quantity of items is being tracked.
     */
    public function getLocationId(): ?string
    {
        if (count($this->locationId) == 0) {
            return null;
        }
        return $this->locationId['value'];
    }

    /**
     * Sets Location Id.
     * The Square-generated ID of the [Location](entity:Location) where the related
     * quantity of items is being tracked.
     *
     * @maps location_id
     */
    public function setLocationId(?string $locationId): void
    {
        $this->locationId['value'] = $locationId;
    }

    /**
     * Unsets Location Id.
     * The Square-generated ID of the [Location](entity:Location) where the related
     * quantity of items is being tracked.
     */
    public function unsetLocationId(): void
    {
        $this->locationId = [];
    }

    /**
     * Returns Catalog Object Id.
     * The Square-generated ID of the
     * [CatalogObject](entity:CatalogObject) being tracked.
     */
    public function getCatalogObjectId(): ?string
    {
        if (count($this->catalogObjectId) == 0) {
            return null;
        }
        return $this->catalogObjectId['value'];
    }

    /**
     * Sets Catalog Object Id.
     * The Square-generated ID of the
     * [CatalogObject](entity:CatalogObject) being tracked.
     *
     * @maps catalog_object_id
     */
    public function setCatalogObjectId(?string $catalogObjectId): void
    {
        $this->catalogObjectId['value'] = $catalogObjectId;
    }

    /**
     * Unsets Catalog Object Id.
     * The Square-generated ID of the
     * [CatalogObject](entity:CatalogObject) being tracked.
     */
    public function unsetCatalogObjectId(): void
    {
        $this->catalogObjectId = [];
    }

    /**
     * Returns Catalog Object Type.
     * The [type](entity:CatalogObjectType) of the [CatalogObject](entity:CatalogObject) being tracked.
     *
     * The Inventory API supports setting and reading the `"catalog_object_type": "ITEM_VARIATION"` field
     * value.
     * In addition, it can also read the `"catalog_object_type": "ITEM"` field value that is set by the
     * EDD\Vendor\Square Restaurants app.
     */
    public function getCatalogObjectType(): ?string
    {
        if (count($this->catalogObjectType) == 0) {
            return null;
        }
        return $this->catalogObjectType['value'];
    }

    /**
     * Sets Catalog Object Type.
     * The [type](entity:CatalogObjectType) of the [CatalogObject](entity:CatalogObject) being tracked.
     *
     * The Inventory API supports setting and reading the `"catalog_object_type": "ITEM_VARIATION"` field
     * value.
     * In addition, it can also read the `"catalog_object_type": "ITEM"` field value that is set by the
     * EDD\Vendor\Square Restaurants app.
     *
     * @maps catalog_object_type
     */
    public function setCatalogObjectType(?string $catalogObjectType): void
    {
        $this->catalogObjectType['value'] = $catalogObjectType;
    }

    /**
     * Unsets Catalog Object Type.
     * The [type](entity:CatalogObjectType) of the [CatalogObject](entity:CatalogObject) being tracked.
     *
     * The Inventory API supports setting and reading the `"catalog_object_type": "ITEM_VARIATION"` field
     * value.
     * In addition, it can also read the `"catalog_object_type": "ITEM"` field value that is set by the
     * EDD\Vendor\Square Restaurants app.
     */
    public function unsetCatalogObjectType(): void
    {
        $this->catalogObjectType = [];
    }

    /**
     * Returns Quantity.
     * The number of items affected by the adjustment as a decimal string.
     * Can support up to 5 digits after the decimal point.
     */
    public function getQuantity(): ?string
    {
        if (count($this->quantity) == 0) {
            return null;
        }
        return $this->quantity['value'];
    }

    /**
     * Sets Quantity.
     * The number of items affected by the adjustment as a decimal string.
     * Can support up to 5 digits after the decimal point.
     *
     * @maps quantity
     */
    public function setQuantity(?string $quantity): void
    {
        $this->quantity['value'] = $quantity;
    }

    /**
     * Unsets Quantity.
     * The number of items affected by the adjustment as a decimal string.
     * Can support up to 5 digits after the decimal point.
     */
    public function unsetQuantity(): void
    {
        $this->quantity = [];
    }

    /**
     * Returns Total Price Money.
     * Represents an amount of money. `Money` fields can be signed or unsigned.
     * Fields that do not explicitly define whether they are signed or unsigned are
     * considered unsigned and can only hold positive amounts. For signed fields, the
     * sign of the value indicates the purpose of the money transfer. See
     * [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-
     * monetary-amounts)
     * for more information.
     */
    public function getTotalPriceMoney(): ?Money
    {
        return $this->totalPriceMoney;
    }

    /**
     * Sets Total Price Money.
     * Represents an amount of money. `Money` fields can be signed or unsigned.
     * Fields that do not explicitly define whether they are signed or unsigned are
     * considered unsigned and can only hold positive amounts. For signed fields, the
     * sign of the value indicates the purpose of the money transfer. See
     * [Working with Monetary Amounts](https://developer.squareup.com/docs/build-basics/working-with-
     * monetary-amounts)
     * for more information.
     *
     * @maps total_price_money
     */
    public function setTotalPriceMoney(?Money $totalPriceMoney): void
    {
        $this->totalPriceMoney = $totalPriceMoney;
    }

    /**
     * Returns Occurred At.
     * A client-generated RFC 3339-formatted timestamp that indicates when
     * the inventory adjustment took place. For inventory adjustment updates, the `occurred_at`
     * timestamp cannot be older than 24 hours or in the future relative to the
     * time of the request.
     */
    public function getOccurredAt(): ?string
    {
        if (count($this->occurredAt) == 0) {
            return null;
        }
        return $this->occurredAt['value'];
    }

    /**
     * Sets Occurred At.
     * A client-generated RFC 3339-formatted timestamp that indicates when
     * the inventory adjustment took place. For inventory adjustment updates, the `occurred_at`
     * timestamp cannot be older than 24 hours or in the future relative to the
     * time of the request.
     *
     * @maps occurred_at
     */
    public function setOccurredAt(?string $occurredAt): void
    {
        $this->occurredAt['value'] = $occurredAt;
    }

    /**
     * Unsets Occurred At.
     * A client-generated RFC 3339-formatted timestamp that indicates when
     * the inventory adjustment took place. For inventory adjustment updates, the `occurred_at`
     * timestamp cannot be older than 24 hours or in the future relative to the
     * time of the request.
     */
    public function unsetOccurredAt(): void
    {
        $this->occurredAt = [];
    }

    /**
     * Returns Created At.
     * An RFC 3339-formatted timestamp that indicates when the inventory adjustment is received.
     */
    public function getCreatedAt(): ?string
    {
        return $this->createdAt;
    }

    /**
     * Sets Created At.
     * An RFC 3339-formatted timestamp that indicates when the inventory adjustment is received.
     *
     * @maps created_at
     */
    public function setCreatedAt(?string $createdAt): void
    {
        $this->createdAt = $createdAt;
    }

    /**
     * Returns Source.
     * Represents information about the application used to generate a change.
     */
    public function getSource(): ?SourceApplication
    {
        return $this->source;
    }

    /**
     * Sets Source.
     * Represents information about the application used to generate a change.
     *
     * @maps source
     */
    public function setSource(?SourceApplication $source): void
    {
        $this->source = $source;
    }

    /**
     * Returns Employee Id.
     * The Square-generated ID of the [Employee](entity:Employee) responsible for the
     * inventory adjustment.
     */
    public function getEmployeeId(): ?string
    {
        if (count($this->employeeId) == 0) {
            return null;
        }
        return $this->employeeId['value'];
    }

    /**
     * Sets Employee Id.
     * The Square-generated ID of the [Employee](entity:Employee) responsible for the
     * inventory adjustment.
     *
     * @maps employee_id
     */
    public function setEmployeeId(?string $employeeId): void
    {
        $this->employeeId['value'] = $employeeId;
    }

    /**
     * Unsets Employee Id.
     * The Square-generated ID of the [Employee](entity:Employee) responsible for the
     * inventory adjustment.
     */
    public function unsetEmployeeId(): void
    {
        $this->employeeId = [];
    }

    /**
     * Returns Team Member Id.
     * The Square-generated ID of the [Team Member](entity:TeamMember) responsible for the
     * inventory adjustment.
     */
    public function getTeamMemberId(): ?string
    {
        if (count($this->teamMemberId) == 0) {
            return null;
        }
        return $this->teamMemberId['value'];
    }

    /**
     * Sets Team Member Id.
     * The Square-generated ID of the [Team Member](entity:TeamMember) responsible for the
     * inventory adjustment.
     *
     * @maps team_member_id
     */
    public function setTeamMemberId(?string $teamMemberId): void
    {
        $this->teamMemberId['value'] = $teamMemberId;
    }

    /**
     * Unsets Team Member Id.
     * The Square-generated ID of the [Team Member](entity:TeamMember) responsible for the
     * inventory adjustment.
     */
    public function unsetTeamMemberId(): void
    {
        $this->teamMemberId = [];
    }

    /**
     * Returns Transaction Id.
     * The Square-generated ID of the [Transaction](entity:Transaction) that
     * caused the adjustment. Only relevant for payment-related state
     * transitions.
     */
    public function getTransactionId(): ?string
    {
        return $this->transactionId;
    }

    /**
     * Sets Transaction Id.
     * The Square-generated ID of the [Transaction](entity:Transaction) that
     * caused the adjustment. Only relevant for payment-related state
     * transitions.
     *
     * @maps transaction_id
     */
    public function setTransactionId(?string $transactionId): void
    {
        $this->transactionId = $transactionId;
    }

    /**
     * Returns Refund Id.
     * The Square-generated ID of the [Refund](entity:Refund) that
     * caused the adjustment. Only relevant for refund-related state
     * transitions.
     */
    public function getRefundId(): ?string
    {
        return $this->refundId;
    }

    /**
     * Sets Refund Id.
     * The Square-generated ID of the [Refund](entity:Refund) that
     * caused the adjustment. Only relevant for refund-related state
     * transitions.
     *
     * @maps refund_id
     */
    public function setRefundId(?string $refundId): void
    {
        $this->refundId = $refundId;
    }

    /**
     * Returns Purchase Order Id.
     * The Square-generated ID of the purchase order that caused the
     * adjustment. Only relevant for state transitions from the EDD\Vendor\Square for Retail
     * app.
     */
    public function getPurchaseOrderId(): ?string
    {
        return $this->purchaseOrderId;
    }

    /**
     * Sets Purchase Order Id.
     * The Square-generated ID of the purchase order that caused the
     * adjustment. Only relevant for state transitions from the EDD\Vendor\Square for Retail
     * app.
     *
     * @maps purchase_order_id
     */
    public function setPurchaseOrderId(?string $purchaseOrderId): void
    {
        $this->purchaseOrderId = $purchaseOrderId;
    }

    /**
     * Returns Goods Receipt Id.
     * The Square-generated ID of the goods receipt that caused the
     * adjustment. Only relevant for state transitions from the EDD\Vendor\Square for Retail
     * app.
     */
    public function getGoodsReceiptId(): ?string
    {
        return $this->goodsReceiptId;
    }

    /**
     * Sets Goods Receipt Id.
     * The Square-generated ID of the goods receipt that caused the
     * adjustment. Only relevant for state transitions from the EDD\Vendor\Square for Retail
     * app.
     *
     * @maps goods_receipt_id
     */
    public function setGoodsReceiptId(?string $goodsReceiptId): void
    {
        $this->goodsReceiptId = $goodsReceiptId;
    }

    /**
     * Returns Adjustment Group.
     */
    public function getAdjustmentGroup(): ?InventoryAdjustmentGroup
    {
        return $this->adjustmentGroup;
    }

    /**
     * Sets Adjustment Group.
     *
     * @maps adjustment_group
     */
    public function setAdjustmentGroup(?InventoryAdjustmentGroup $adjustmentGroup): void
    {
        $this->adjustmentGroup = $adjustmentGroup;
    }

    /**
     * Encode this object to JSON
     *
     * @param bool $asArrayWhenEmpty Whether to serialize this model as an array whenever no fields
     *        are set. (default: false)
     *
     * @return array|stdClass
     */
    #[\ReturnTypeWillChange] // @phan-suppress-current-line PhanUndeclaredClassAttribute for (php < 8.1)
    public function jsonSerialize(bool $asArrayWhenEmpty = false)
    {
        $json = [];
        if (isset($this->id)) {
            $json['id']                  = $this->id;
        }
        if (!empty($this->referenceId)) {
            $json['reference_id']        = $this->referenceId['value'];
        }
        if (isset($this->fromState)) {
            $json['from_state']          = $this->fromState;
        }
        if (isset($this->toState)) {
            $json['to_state']            = $this->toState;
        }
        if (!empty($this->locationId)) {
            $json['location_id']         = $this->locationId['value'];
        }
        if (!empty($this->catalogObjectId)) {
            $json['catalog_object_id']   = $this->catalogObjectId['value'];
        }
        if (!empty($this->catalogObjectType)) {
            $json['catalog_object_type'] = $this->catalogObjectType['value'];
        }
        if (!empty($this->quantity)) {
            $json['quantity']            = $this->quantity['value'];
        }
        if (isset($this->totalPriceMoney)) {
            $json['total_price_money']   = $this->totalPriceMoney;
        }
        if (!empty($this->occurredAt)) {
            $json['occurred_at']         = $this->occurredAt['value'];
        }
        if (isset($this->createdAt)) {
            $json['created_at']          = $this->createdAt;
        }
        if (isset($this->source)) {
            $json['source']              = $this->source;
        }
        if (!empty($this->employeeId)) {
            $json['employee_id']         = $this->employeeId['value'];
        }
        if (!empty($this->teamMemberId)) {
            $json['team_member_id']      = $this->teamMemberId['value'];
        }
        if (isset($this->transactionId)) {
            $json['transaction_id']      = $this->transactionId;
        }
        if (isset($this->refundId)) {
            $json['refund_id']           = $this->refundId;
        }
        if (isset($this->purchaseOrderId)) {
            $json['purchase_order_id']   = $this->purchaseOrderId;
        }
        if (isset($this->goodsReceiptId)) {
            $json['goods_receipt_id']    = $this->goodsReceiptId;
        }
        if (isset($this->adjustmentGroup)) {
            $json['adjustment_group']    = $this->adjustmentGroup;
        }
        $json = array_filter($json, function ($val) {
            return $val !== null;
        });

        return (!$asArrayWhenEmpty && empty($json)) ? new stdClass() : $json;
    }
}
