//>>> _using
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.Windows;
//<<< _using
using System.IO;
using SharpDX.DXGI;

namespace Framefield.Core.ID27806659_b530_478d_b23d_914fdad02bee
{
    public class Class_CubeMapFromImages : OperatorPart.Function
    {
        //>>> _inputids
        private enum InputId
        {
            RightImage = 0,
            LeftImage = 1,
            TopImage = 2,
            BottomImage = 3,
            FrontImage = 4,
            BackImage = 5
        }
        //<<< _inputids

        public override void Dispose()
        {
            ResourceManager.Dispose(_cubeImageResource);
            base.Dispose();
        }

        private bool BuildTextureArray(OperatorPartContext context, Texture2D[] singleTextures)
        {
            if (singleTextures.Count() != 6)
                return false;

            var textureDesc = ResourceManager.GetTextureDescription(BindFlags.ShaderResource,
                                                                    singleTextures[0].Description.Format,
                                                                    singleTextures[0].Description.Width,
                                                                    singleTextures[0].Description.Height);
            textureDesc.MipLevels = singleTextures[0].Description.MipLevels;
            textureDesc.OptionFlags = ResourceOptionFlags.TextureCube;
            textureDesc.ArraySize = 6;
            ResourceManager.ValidateResource(ref _cubeImageResource, OperatorPart, context.D3DDevice, textureDesc);

            if (_cubeImageResource == null || _cubeImageResource.Texture == null)
                return false;

            var dxContext = context.D3DDevice.ImmediateContext;
            Texture2D targetCubeTexture = _cubeImageResource.Texture;
            for (int arraySlice = 0; arraySlice < singleTextures.Count(); ++arraySlice)
            {
                Texture2D texture = singleTextures[arraySlice];
                if (texture == null)
                    return false;

                for (int mipSlice = 0; mipSlice < texture.Description.MipLevels; ++mipSlice)
                {
                    int mipSize;
                    int idx = targetCubeTexture.CalculateSubResourceIndex(mipSlice, arraySlice, out mipSize);
                    dxContext.CopySubresourceRegion(texture, mipSlice, null, targetCubeTexture, idx);
                }
            }
            return true;
        }
        
        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) 
        {
            if (Changed)
            {
                //>>> _params
                var RightImage = inputs[(int)InputId.RightImage].Eval(context).Image; // Needs to be checked for null!
                var LeftImage = inputs[(int)InputId.LeftImage].Eval(context).Image; // Needs to be checked for null!
                var TopImage = inputs[(int)InputId.TopImage].Eval(context).Image; // Needs to be checked for null!
                var BottomImage = inputs[(int)InputId.BottomImage].Eval(context).Image; // Needs to be checked for null!
                var FrontImage = inputs[(int)InputId.FrontImage].Eval(context).Image; // Needs to be checked for null!
                var BackImage = inputs[(int)InputId.BackImage].Eval(context).Image; // Needs to be checked for null!
                //<<< _params

                var currentImages = new[] { RightImage, LeftImage, TopImage, BottomImage, FrontImage, BackImage };
                if (BuildTextureArray(context, currentImages))
                    Changed = false;
            }

            if (_cubeImageResource != null && _cubeImageResource.Texture != null)
                context.Image = _cubeImageResource.Texture;

            return context;
        }

        Resource _cubeImageResource;
    }
}

