using System;
using System.Collections.Generic;
using System.Threading;
using Ozeki.VoIP;

namespace _10_MultiSIPAccount
{
    class Autodialer
    {
        Softphone _softphone;
        List<CallInfo> _callList;
        int _maxConcurrentCall;
        int _currentConcurrentCall;
        List<CallHandler> _callHandlers;
        AutoResetEvent _autoResetEvent;

        object _sync;

        public Autodialer(Softphone softphone, List<CallInfo> callList, int maxConcurrentCall)
        {
            _sync = new object();
            _softphone = softphone;
            _callList = callList;
            _maxConcurrentCall = maxConcurrentCall;
            _callHandlers = new List<CallHandler>();
            _autoResetEvent = new AutoResetEvent(false);
        }
        
        /// <summary>
        /// The autodialer begins to work, starts to call the first client.
        /// </summary>
        public void Start()
        {
            ThreadPool.QueueUserWorkItem(o =>
            //Task.Factory.StartNew(() =>
            {
                foreach (var callInfo in _callList)
                {
                    if (_currentConcurrentCall < _maxConcurrentCall && _softphone.GetAvailablePhoneLineCount() > 0)
                    {
                        StartCallHandler(callInfo);
                    }
                    else
                    {
                        _autoResetEvent.WaitOne();
                        StartCallHandler(callInfo);
                    }
                }
            });
        }

        void StartCallHandler(CallInfo callInfo)
        {
            lock (_sync)
            {
                ++_currentConcurrentCall;
                var callHandler = new CallHandler(_softphone, callInfo);
                callHandler.Completed += callHandler_Completed;
                _callHandlers.Add(callHandler);

                IPhoneLine phoneLine = GetLine(callInfo);   // the call will be made via the selected phone line (sip account)
                callHandler.Start(phoneLine);
            }
        }

        void callHandler_Completed(object sender, EventArgs e)
        {
            lock (_sync)
            {
                _callHandlers.Remove((CallHandler)sender);
                --_currentConcurrentCall;
                _autoResetEvent.Set();
            }
        }

        /// <summary>
        /// Provides the opportunity to create custom dial plans (call routings) for specified phone numbers etc.
        /// </summary>
        /// <param name="callInfo"></param>
        /// <returns></returns>
        IPhoneLine GetLine(CallInfo callInfo)
        {
            IPhoneLine phoneLine = _softphone.GetAvailablePhoneLine();
            
            /*
            var number = callInfo.PhoneNumber;
            
            if (number.Equals("+44123456789"))
            {
                phoneLine = _softphone.GetAvailablePhoneLine("1001", "192.168.112.215");
            }
            */

            _softphone.RemoveAvailablePhoneLine(phoneLine);
            return phoneLine;
        }
    }
}
