/**
 * Copyright(c) Live2D Inc. All rights reserved.
 *
 * Use of this source code is governed by the Live2D Open Software license
 * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
 */
using UnityEngine.Rendering;
namespace Live2D.Cubism.Rendering.Masking
{
    /// 
    /// Many-to-many - map.
    /// 
    internal sealed class CubismMaskMaskedJunction
    {
        /// 
        /// Shared buffer for s.
        /// 
        private static CubismMaskProperties SharedMaskProperties { get; set; }
        /// 
        /// Masks.
        /// 
        private CubismMaskRenderer[] Masks { get; set; }
        /// 
        /// Masked drawables.
        /// 
        private CubismRenderer[] Maskeds { get; set; }
        /// 
        /// Mask texture to be referenced by .
        /// 
        private CubismMaskTexture MaskTexture { get; set; }
        /// 
        /// Mask tile to write to and read from.
        /// 
        private CubismMaskTile MaskTile { get; set; }
        /// 
        /// Mask transform
        /// 
        private CubismMaskTransform MaskTransform { get; set; }
        #region Ctors
        /// 
        /// Makes sure statics are initialized.
        /// 
        public CubismMaskMaskedJunction()
        {
            if (SharedMaskProperties != null)
            {
                return;
            }
            SharedMaskProperties = new CubismMaskProperties();
        }
        #endregion
        #region Interface For CubismMaskController
        /// 
        /// Sets the masks.
        /// 
        /// Value to set.
        /// Instance.
        public CubismMaskMaskedJunction SetMasks(CubismMaskRenderer[] value)
        {
            Masks = value;
            return this;
        }
        /// 
        /// Sets the masked drawables.
        /// 
        /// Value to set.
        /// Instance.
        public CubismMaskMaskedJunction SetMaskeds(CubismRenderer[] value)
        {
            Maskeds = value;
            return this;
        }
        /// 
        /// Sets the mask texture to read from.
        /// 
        /// Value to set.
        /// Instance.
        public CubismMaskMaskedJunction SetMaskTexture(CubismMaskTexture value)
        {
            MaskTexture = value;
            return this;
        }
        /// 
        /// Sets the mask tile to write to and read from.
        /// 
        /// Value to set.
        /// Instance.
        public CubismMaskMaskedJunction SetMaskTile(CubismMaskTile value)
        {
            MaskTile = value;
            return this;
        }
        /// 
        /// Appends junction draw commands to a buffer.
        /// 
        /// Buffer to append commands to.
        public void AddToCommandBuffer(CommandBuffer buffer)
        {
            // Make sure mask transform is initialized.
            RecalculateMaskTransform();
            // Initialize and enqueue masks.
            for (var i = 0; i < Masks.Length; ++i)
            {
                Masks[i]
                    .SetMaskTile(MaskTile)
                    .SetMaskTransform(MaskTransform)
                    .AddToCommandBuffer(buffer);
            }
        }
        /// 
        /// Updates the junction and all related data.
        /// 
        internal void Update()
        {
            // Update mask transform.
            RecalculateMaskTransform();
            // Apply transform to masks.
            for (var i = 0; i < Masks.Length; ++i)
            {
                Masks[i].SetMaskTransform(MaskTransform);
            }
            // Apply transform and other properties to maskeds.
            var maskProperties = SharedMaskProperties;
            maskProperties.Texture = MaskTexture;
            maskProperties.Tile = MaskTile;
            maskProperties.Transform = MaskTransform;
            for (var i = 0; i < Maskeds.Length; ++i)
            {
                Maskeds[i].OnMaskPropertiesDidChange(maskProperties);
            }
        }
        #endregion
        /// 
        /// Updates  and .
        /// 
        private void RecalculateMaskTransform()
        {
            // Compute bounds and scale.
            var bounds = Masks.GetBounds();
            var scale = (bounds.size.x > bounds.size.y)
                ? bounds.size.x
                : bounds.size.y;
            // Compute mask transform.
            MaskTransform = new CubismMaskTransform
            {
                Offset = bounds.center,
                Scale = 1f / scale
            };
        }
    }
}