using System;
using System.Threading.Tasks;
using System.Windows.Threading;
using ThomsonReuters.Desktop.SDK.DataAccess;
using ThomsonReuters.Desktop.SDK.DataAccess.TimeSeries;
using System.Threading;

namespace ReutersTestCase
{
    class Program
    {
        static void Main(string[] args)
        {
            var testCode = new TestCode();


            //initialize
            testCode.Initialize();


            var task1 = Task.Run(() =>
            {
                testCode.SubmitRequest();
            }).ContinueWith(a =>
            {
                var task2 = Task.Run(() =>
                {
                    testCode.SubmitRequest();
                }).ContinueWith(b =>
                {
                    var task3 = Task.Run(() =>
                    {
                        testCode.SubmitRequest();
                    });
                }).ContinueWith(c =>
                {
                    var task4 = Task.Run(() =>
                    {
                        testCode.SubmitRequest();
                    });
                }); 
            });



            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }
    }


    public class TestCode
    {
        private int _iterationId;
        private IDataServices _currentDataService;
        private ITimeSeriesDataService _timeSeriesServices;
        private ITimeSeriesDataRequest _currentRequest;
        private DispatcherFrame _currentFrame;
        private Dispatcher _currentDispatcher;
        private bool _isInitCompleted;
        private bool _isRequestCompleted;
        ManualResetEvent dispatcherReadyEvent = new ManualResetEvent(false);

        public TestCode()
        {
            _isInitCompleted = false;
            new Thread(new ThreadStart(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                _currentDispatcher = Dispatcher.CurrentDispatcher;
                dispatcherReadyEvent.Set();
                Dispatcher.Run();
            })).Start();
         //   _currentDispatcher = Dispatcher.CurrentDispatcher;
            dispatcherReadyEvent.WaitOne();
        }


        public void Initialize()
        {
            

             PushDispatcherFrame(new Action(() =>
            {
                _currentFrame = new DispatcherFrame();
                _currentDataService = DataServices.Instance;
                _currentDataService.StateChanged += CurrentDataServiceOnStateChanged;
                _currentDataService.Initialize("TestApp");
                _timeSeriesServices = DataServices.Instance.TimeSeries;
                _timeSeriesServices.ServiceInformationChanged += TimeSeriesServicesOnServiceInformationChanged;
                Dispatcher.PushFrame(_currentFrame);               

            }));
            


            //wait hack
            while (_isInitCompleted == false)
            {
                Task.Delay(200).Wait();
            }


            Console.WriteLine("Init completed");
        }


        public void SubmitRequest()
        {
            Console.WriteLine("Submit Request");
            PushDispatcherFrame(new Action(() =>
            {
                _isRequestCompleted = false;


                _currentFrame = new DispatcherFrame();


                _currentRequest = _timeSeriesServices.SetupDataRequest("EUR=")
                    .WithView("BID")
                    .WithAllFields()
                    .WithInterval(CommonInterval.Daily)
                    .WithNumberOfPoints(20)
                    .OnDataReceived(DataReceivedCallback)
                    .CreateAndSend();


                Dispatcher.PushFrame(_currentFrame);








                //wait hack
                while (_isRequestCompleted == false)
                {
                    Task.Delay(200).Wait();
                }
            }));
        }


        private void CurrentDataServiceOnStateChanged(object sender, DataServicesStateChangedEventArgs dataServicesStateChangedEventArgs)
        {
            ReleaseFrame(false);
            _isInitCompleted = true;
        }


        private void TimeSeriesServicesOnServiceInformationChanged(object sender, ServiceInformationChangedEventArgs serviceInformationChangedEventArgs)
        {
            //do nothing here
        }


        private void DataReceivedCallback(DataChunk chunk)
        {
            foreach (IBarData bar in chunk.Records.ToBarRecords())
            {
                if (bar.Open.HasValue && bar.High.HasValue && bar.Low.HasValue && bar.Close.HasValue && bar.Timestamp.HasValue)
                {
                    Console.WriteLine(
                        "{0}: EUR= OHLC {1} {2} {3} {4}",
                        bar.Timestamp.Value.ToShortDateString(),
                        bar.Open.Value.ToString("##.0000"),
                        bar.High.Value.ToString("##.0000"),
                        bar.Low.Value.ToString("##.0000"),
                        bar.Close.Value.ToString("##.0000")
                    );



                };
            }


            if (!chunk.IsLast)
                return;

            ReleaseFrame(false);


            Console.WriteLine();


            _currentRequest = null;
            _isRequestCompleted = true;
        }


        private void PushDispatcherFrame(Action action)
        {
            _currentDispatcher.Invoke(() =>
            {
                //create new frame
               _currentFrame = new DispatcherFrame();


                //execute action
                action();


                //push frame
               Dispatcher.PushFrame(_currentFrame);
            });
        }


        private void ReleaseFrame(bool isContinue)
        {
            _currentDispatcher.Invoke(() =>
            {
                _currentFrame.Continue = isContinue;
            });
        }
    }
}