private void OnTerminalDropCall(object sender, EventArgs e)
        {
            var terminal = sender as ClientTerminal;
            if (terminal == null) return;

            var client = BillingSystem.Contracts.First(c => c.Terminal == terminal);
            var sessions = CurrentSessions.Where(s => s.Source == client || s.Target == client).ToList();
            if (!sessions.Any()) return;

            var session = sessions.First();
            var systemTime = DateTime.Now;
            var callingEventTime = session.Events.First().EventTime;
            var currentTime = new DateTime(callingEventTime.Year, callingEventTime.Month, callingEventTime.Day, systemTime.Hour, systemTime.Minute, systemTime.Second);
            var connEvent = new ConnectionEvent(client, ConnectionEventType.Droped, currentTime);
            session.Events.Add(connEvent);
            session.EndCalling = currentTime;

            CurrentSessions.Remove(session);
            BillingSystem.SessionHistory.Add(session);

            var isTarget = session.Target == client;
            if (isTarget)
            {
                session.Source.Terminal.ReceiveResponce(ResponceState.Droped);
            }
            else
            {
                session.Target.Terminal.ReceiveResponce(ResponceState.Droped);
            }
        }
        private void OnTerminalAcceptCall(object sender, EventArgs e)
        {
            var targetTerminal = sender as ClientTerminal;
            if (targetTerminal == null) return;

            var targetClient = BillingSystem.Contracts.First(c => c.Terminal == targetTerminal);
            var sessions = CurrentSessions.Where(s => s.Target == targetClient).ToList();
            if (!sessions.Any()) return;

            var session = sessions.First();
            var systemTime = DateTime.Now;
            var callingEventTime = session.Events.First().EventTime;
            var currentTime = new DateTime(callingEventTime.Year, callingEventTime.Month, callingEventTime.Day, systemTime.Hour, systemTime.Minute, systemTime.Second);
            var connEvent = new ConnectionEvent(targetClient, ConnectionEventType.Accepted, currentTime);
            session.Events.Add(connEvent);
            session.StartCalling = currentTime;

            session.Source.Terminal.ReceiveResponce(ResponceState.Accepted);
        }
        private void OnTerminalCalling(object sender, CallingRequest e)
        {
            var sourceTerminal = sender as ClientTerminal;
            if (sourceTerminal == null) return;

            var sourceClient = BillingSystem.Contracts.First(c => c.Terminal == sourceTerminal);
            var sourceTelephoneNumber = sourceClient.TelephoneNumber;
            var incommingRequest = new InCommingRequest(sourceTelephoneNumber);

            var clients = BillingSystem.Contracts.Where(c => c.TelephoneNumber == e.Target);
            // Target number doesn't exist
            if (!clients.Any())
            {
                sourceTerminal.ReceiveResponce(ResponceState.DoesNotExist);
                return;
            }

            var targetClient = clients.First();
            var session = new Session(sourceClient, targetClient, sourceClient.Rate);
            var systemTime = DateTime.Now;
            var currentTime = new DateTime(BillingSystem.CurrentTime.Year, BillingSystem.CurrentTime.Month, systemTime.Day, systemTime.Hour, systemTime.Minute, systemTime.Second);
            var connEvent = new ConnectionEvent(targetClient, ConnectionEventType.Accepted, currentTime);
            session.Events.Add(connEvent);

            var targetPort = _terminalToPertConnections.First(c => c.Terminal == targetClient.Terminal).Port;
            switch (targetPort.State)
            {
                case ConnectionState.Free:
                    {
                        sourceTerminal.ReceiveResponce(ResponceState.Calling);
                        CurrentSessions.Add(session);

                        targetClient.Terminal.IncomingRequestFrom(incommingRequest);
                        break;
                    }
                case ConnectionState.Busy:
                    {
                        sourceTerminal.ReceiveResponce(ResponceState.IsBusy);
                        BillingSystem.SessionHistory.Add(session);
                        break;
                    }
                case ConnectionState.UnConnected:
                    {
                        sourceTerminal.ReceiveResponce(ResponceState.UnConnected);
                        BillingSystem.SessionHistory.Add(session);
                        break;
                    }
            }
        }
        private void OnPortStateChanged(object sender, ConnectionState e)
        {
            if (e != ConnectionState.UnConnected) return;

            var port = sender as Port;
            if (port == null) return;

            var connections = _terminalToPertConnections.Where(c => c.Port == port).ToList();
            if (!connections.Any()) return;

            var connection = connections.First();
            var sourceTerminal = connection.Terminal;
            var sourceClient = BillingSystem.Contracts.First(c => c.Terminal == sourceTerminal);

            // if there is no session, connected with current terminal, do nothing
            var sessions = CurrentSessions.Where(s => s.Source == sourceClient || s.Target == sourceClient).ToList();
            if (!sessions.Any()) return;

            var session = sessions.First();
            var systemTime = DateTime.Now;
            var callingEventTime = session.Events.First().EventTime;
            var currentTime = new DateTime(callingEventTime.Year, callingEventTime.Month, callingEventTime.Day, systemTime.Hour, systemTime.Minute, systemTime.Second);
            var connEvent = new ConnectionEvent(sourceClient, ConnectionEventType.Disconnected, currentTime);
            // end this session
            session.Events.Add(connEvent);
            session.EndCalling = currentTime;

            CurrentSessions.Remove(session);
            BillingSystem.SessionHistory.Add(session);

            var isTarget = session.Target == sourceClient;
            if (isTarget)
            {
                session.Source.Terminal.ReceiveResponce(ResponceState.UnConnected);
            }
            else
            {
                session.Target.Terminal.ReceiveResponce(ResponceState.UnConnected);
            }
        }