<?php
/**
 * InputSettingsOverlaySettings
 *
 * PHP version 7.2
 *
 * @category Class
 * @package  MuxPhp
 * @author   Mux API team
 * @link     https://docs.mux.com
 */

/**
 * Mux API
 *
 * Mux is how developers build online video. This API encompasses both Mux Video and Mux Data functionality to help you build your video-related projects better and faster than ever before.
 *
 * The version of the OpenAPI document: v1
 * Contact: devex@mux.com
 * Generated by: https://openapi-generator.tech
 * OpenAPI Generator version: 5.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 MuxPhp\Models;

use \ArrayAccess;
use \MuxPhp\ObjectSerializer;

/**
 * InputSettingsOverlaySettings Class Doc Comment
 *
 * @category Class
 * @description An object that describes how the image file referenced in URL should be placed over the video (i.e. watermarking). Ensure that the URL is active and persists the entire lifespan of the video object.
 * @package  MuxPhp
 * @author   Mux API team
 * @link     https://docs.mux.com
 * @implements \ArrayAccess<TKey, TValue>
 * @template TKey int|null
 * @template TValue mixed|null  
 */
class InputSettingsOverlaySettings implements ModelInterface, ArrayAccess, \JsonSerializable
{
    public const DISCRIMINATOR = null;

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

    /**
      * Array of property to type mappings. Used for (de)serialization
      *
      * @var string[]
      */
    protected static $openAPITypes = [
        'vertical_align' => 'string',
        'vertical_margin' => 'string',
        'horizontal_align' => 'string',
        'horizontal_margin' => 'string',
        'width' => 'string',
        'height' => 'string',
        'opacity' => '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 = [
        'vertical_align' => null,
        'vertical_margin' => null,
        'horizontal_align' => null,
        'horizontal_margin' => null,
        'width' => null,
        'height' => null,
        'opacity' => null
    ];

    /**
      * Array of nullable properties. Used for (de)serialization
      *
      * @var boolean[]
      */
    protected static array $openAPINullables = [
        'vertical_align' => false,
        'vertical_margin' => false,
        'horizontal_align' => false,
        'horizontal_margin' => false,
        'width' => false,
        'height' => false,
        'opacity' => 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;
    }

    /**
     * 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 = [
        'vertical_align' => 'vertical_align',
        'vertical_margin' => 'vertical_margin',
        'horizontal_align' => 'horizontal_align',
        'horizontal_margin' => 'horizontal_margin',
        'width' => 'width',
        'height' => 'height',
        'opacity' => 'opacity'
    ];

    /**
     * Array of attributes to setter functions (for deserialization of responses)
     *
     * @var string[]
     */
    protected static $setters = [
        'vertical_align' => 'setVerticalAlign',
        'vertical_margin' => 'setVerticalMargin',
        'horizontal_align' => 'setHorizontalAlign',
        'horizontal_margin' => 'setHorizontalMargin',
        'width' => 'setWidth',
        'height' => 'setHeight',
        'opacity' => 'setOpacity'
    ];

    /**
     * Array of attributes to getter functions (for serialization of requests)
     *
     * @var string[]
     */
    protected static $getters = [
        'vertical_align' => 'getVerticalAlign',
        'vertical_margin' => 'getVerticalMargin',
        'horizontal_align' => 'getHorizontalAlign',
        'horizontal_margin' => 'getHorizontalMargin',
        'width' => 'getWidth',
        'height' => 'getHeight',
        'opacity' => 'getOpacity'
    ];

    /**
     * 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 VERTICAL_ALIGN_TOP = 'top';
    public const VERTICAL_ALIGN_MIDDLE = 'middle';
    public const VERTICAL_ALIGN_BOTTOM = 'bottom';
    public const HORIZONTAL_ALIGN_LEFT = 'left';
    public const HORIZONTAL_ALIGN_CENTER = 'center';
    public const HORIZONTAL_ALIGN_RIGHT = 'right';

    /**
     * Gets allowable values of the enum
     *
     * @return string[]
     */
    public function getVerticalAlignAllowableValues()
    {
        return [
            self::VERTICAL_ALIGN_TOP,
            self::VERTICAL_ALIGN_MIDDLE,
            self::VERTICAL_ALIGN_BOTTOM,
        ];
    }

    /**
     * Gets allowable values of the enum
     *
     * @return string[]
     */
    public function getHorizontalAlignAllowableValues()
    {
        return [
            self::HORIZONTAL_ALIGN_LEFT,
            self::HORIZONTAL_ALIGN_CENTER,
            self::HORIZONTAL_ALIGN_RIGHT,
        ];
    }

    /**
     * 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)
    {
        // MUX: enum hack (self::) due to OAS emitting problems.
        //      please re-integrate with mainline when possible.
        //      src: https://github.com/OpenAPITools/openapi-generator/issues/9038
        $this->setIfExists('vertical_align', $data ?? [], null);
        $this->setIfExists('vertical_margin', $data ?? [], null);
        $this->setIfExists('horizontal_align', $data ?? [], null);
        $this->setIfExists('horizontal_margin', $data ?? [], null);
        $this->setIfExists('width', $data ?? [], null);
        $this->setIfExists('height', $data ?? [], null);
        $this->setIfExists('opacity', $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->getVerticalAlignAllowableValues();
        if (!is_null($this->container['vertical_align']) && !in_array($this->container['vertical_align'], $allowedValues, true)) {
            $invalidProperties[] = sprintf(
                "invalid value '%s' for 'vertical_align', must be one of '%s'",
                $this->container['vertical_align'],
                implode("', '", $allowedValues)
            );
        }

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

    /**
     * Sets vertical_align
     *
     * @param string|null $vertical_align Where the vertical positioning of the overlay/watermark should begin from. Defaults to `\"top\"`
     *
     * @return self
     */
    public function setVerticalAlign($vertical_align)
    {
        $allowedValues = $this->getVerticalAlignAllowableValues();
        if (!is_null($vertical_align) && !in_array($vertical_align, $allowedValues, true)) {
            throw new \InvalidArgumentException(
                sprintf(
                    "Invalid value '%s' for 'vertical_align', must be one of '%s'",
                    $vertical_align,
                    implode("', '", $allowedValues)
                )
            );
        }

        if (is_null($vertical_align)) {
            throw new \InvalidArgumentException('non-nullable vertical_align cannot be null');
        }

        $this->container['vertical_align'] = $vertical_align;

        return $this;
    }

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

    /**
     * Sets vertical_margin
     *
     * @param string|null $vertical_margin The distance from the vertical_align starting point and the image's closest edge. Can be expressed as a percent (\"10%\") or as a pixel value (\"100px\"). Negative values will move the overlay offscreen. In the case of 'middle', a positive value will shift the overlay towards the bottom and and a negative value will shift it towards the top.
     *
     * @return self
     */
    public function setVerticalMargin($vertical_margin)
    {

        if (is_null($vertical_margin)) {
            throw new \InvalidArgumentException('non-nullable vertical_margin cannot be null');
        }

        $this->container['vertical_margin'] = $vertical_margin;

        return $this;
    }

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

    /**
     * Sets horizontal_align
     *
     * @param string|null $horizontal_align Where the horizontal positioning of the overlay/watermark should begin from.
     *
     * @return self
     */
    public function setHorizontalAlign($horizontal_align)
    {
        $allowedValues = $this->getHorizontalAlignAllowableValues();
        if (!is_null($horizontal_align) && !in_array($horizontal_align, $allowedValues, true)) {
            throw new \InvalidArgumentException(
                sprintf(
                    "Invalid value '%s' for 'horizontal_align', must be one of '%s'",
                    $horizontal_align,
                    implode("', '", $allowedValues)
                )
            );
        }

        if (is_null($horizontal_align)) {
            throw new \InvalidArgumentException('non-nullable horizontal_align cannot be null');
        }

        $this->container['horizontal_align'] = $horizontal_align;

        return $this;
    }

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

    /**
     * Sets horizontal_margin
     *
     * @param string|null $horizontal_margin The distance from the horizontal_align starting point and the image's closest edge. Can be expressed as a percent (\"10%\") or as a pixel value (\"100px\"). Negative values will move the overlay offscreen. In the case of 'center', a positive value will shift the image towards the right and and a negative value will shift it towards the left.
     *
     * @return self
     */
    public function setHorizontalMargin($horizontal_margin)
    {

        if (is_null($horizontal_margin)) {
            throw new \InvalidArgumentException('non-nullable horizontal_margin cannot be null');
        }

        $this->container['horizontal_margin'] = $horizontal_margin;

        return $this;
    }

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

    /**
     * Sets width
     *
     * @param string|null $width How wide the overlay should appear. Can be expressed as a percent (\"10%\") or as a pixel value (\"100px\"). If both width and height are left blank the width will be the true pixels of the image, applied as if the video has been scaled to fit a 1920x1080 frame. If height is supplied with no width, the width will scale proportionally to the height.
     *
     * @return self
     */
    public function setWidth($width)
    {

        if (is_null($width)) {
            throw new \InvalidArgumentException('non-nullable width cannot be null');
        }

        $this->container['width'] = $width;

        return $this;
    }

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

    /**
     * Sets height
     *
     * @param string|null $height How tall the overlay should appear. Can be expressed as a percent (\"10%\") or as a pixel value (\"100px\"). If both width and height are left blank the height will be the true pixels of the image, applied as if the video has been scaled to fit a 1920x1080 frame. If width is supplied with no height, the height will scale proportionally to the width.
     *
     * @return self
     */
    public function setHeight($height)
    {

        if (is_null($height)) {
            throw new \InvalidArgumentException('non-nullable height cannot be null');
        }

        $this->container['height'] = $height;

        return $this;
    }

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

    /**
     * Sets opacity
     *
     * @param string|null $opacity How opaque the overlay should appear, expressed as a percent. (Default 100%)
     *
     * @return self
     */
    public function setOpacity($opacity)
    {

        if (is_null($opacity)) {
            throw new \InvalidArgumentException('non-nullable opacity cannot be null');
        }

        $this->container['opacity'] = $opacity;

        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(): string
    {
        return json_encode(
            ObjectSerializer::sanitizeForSerialization($this),
            JSON_PRETTY_PRINT
        );
    }

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


