//>>> _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 System.Net;

namespace Framefield.Core.IDf54bedba_e90a_4512_8589_a69e2bb9b7df
{
    public class Class_LoadImageURI : OperatorPart.Function,
                                      OperatorPartTraits.IAsyncDependend
    {
        //>>> _inputids
        private enum InputId
        {
            Uri = 0
        }
        //<<< _inputids

        //>>> _outputids
        private enum OutputId
        {
            Image = 0,
            SizeX = 1,
            SizeY = 2
        }
        //<<< _outputids

        public bool AsyncChanged { get { return _asyncChanged; } }

        public override void Dispose()
        {
            lock (_lock)
            {
                Utilities.DisposeObj(ref _image);
            }
        }

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)
        {
            //>>> _params
            var Uri = inputs[(int)InputId.Uri].Eval(context).Text;
            //<<< _params

            if (_image == null || Uri != _uri)
            {
                if (_webRequest == null)
                {
                    Dispose();
                    try
                    {
                        _webRequest = WebRequest.Create(Uri);
                        _uri = Uri;
                        DoGETRequest(_webRequest, HandleResponse);
                    }
                    catch (Exception e)
                    {
                        Logger.Error("failed to start request: {0}", e.Message);
                    }
                }
            }

            lock (_lock)
            {
                switch (outputIdx)
                {
                    case (int)OutputId.Image: context.Image = _image; break;
                    case (int)OutputId.SizeX: context.Value = _image != null ? _image.Description.Width : 0; break;
                    case (int)OutputId.SizeY: context.Value = _image != null ? _image.Description.Height : 0; break;
                }
                _asyncChanged = false;
            }
            return context;
        }

        void DoGETRequest(WebRequest request, Action<WebResponse> responseAction)
        {
            Action wrapperAction = () =>
            {
                request.BeginGetResponse(new AsyncCallback((iar) =>
                                         {
                                             try
                                             {
                                                 WebRequest req = (WebRequest)iar.AsyncState;
                                                 var response = req.EndGetResponse(iar);
                                                 responseAction(response);
                                             }
                                             catch (Exception)
                                             {
                                             }
                                             _webRequest = null;
                                         }),
                                         request);
            };
            wrapperAction.BeginInvoke(new AsyncCallback((iar) =>
                                      {
                                          var action = (Action)iar.AsyncState;
                                          action.EndInvoke(iar);
                                      }),
                                      wrapperAction);
        }

        void HandleResponse(WebResponse response)
        {
            try
            {
                using (var memStream = new MemoryStream())
                using (Stream streamResponse = response.GetResponseStream())
                {
                    streamResponse.CopyTo(memStream);
                    lock (_lock)
                    {
                        _image = SharpDX.Direct3D11.Resource.FromMemory<Texture2D>(D3DDevice.Device, memStream.ToArray());
                        _asyncChanged = true;
                    }
                }
                response.Close();
            }
            catch (Exception)
            {
                lock (_lock)
                    _image = null;
            }
        }

        Object _lock = new Object();
        bool _asyncChanged = false;
        WebRequest _webRequest;
        Texture2D _image;
        String _uri = String.Empty;
    }
}

