private void DoSetChannelStates(Dictionary <int, ITvCardHandler> cards, ICollection <Channel> channels,
                                        bool checkTransponders, IList <IUser> allUsers, TVController tvController)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();

            try
            {
                //construct list of all cards we can use to tune to the new channel
                Log.Debug("Controller: DoSetChannelStates for {0} channels", channels.Count);

                if (allUsers == null || allUsers.Count == 0)
                {
                    return; // no users, no point in continuing.
                }

                TvBusinessLayer layer = new TvBusinessLayer();

                Dictionary <int, ChannelState> TSandRecStates = null;

                Dictionary <int, ITvCardHandler> .ValueCollection cardHandlers = cards.Values;

                IDictionary <int, IList <int> >      channelMapping       = GetChannelMapping();
                IDictionary <int, IList <IChannel> > tuningChannelMapping = GetTuningChannels();
                foreach (Channel ch in channels)
                {
                    if (!ch.VisibleInGuide)
                    {
                        UpdateChannelStateUsers(allUsers, ChannelState.nottunable, ch.IdChannel);
                        continue;
                    }

                    //get the tuning details for the channel
                    IList <IChannel> tuningDetails;
                    tuningChannelMapping.TryGetValue(ch.IdChannel, out tuningDetails);
                    bool isValidTuningDetails = IsValidTuningDetails(tuningDetails);
                    if (!isValidTuningDetails)
                    {
                        UpdateChannelStateUsers(allUsers, ChannelState.nottunable, ch.IdChannel);
                        continue;
                    }

                    foreach (IChannel tuningDetail in tuningDetails)
                    {
                        foreach (ITvCardHandler cardHandler in cardHandlers)
                        {
                            int cardId = cardHandler.DataBaseCard.IdCard;

                            //check if card is enabled
                            if (!cardHandler.DataBaseCard.Enabled)
                            {
                                //not enabled, so skip the card
                                //Log.Info("Controller:    card:{0} type:{1} is disabled", cardId, tvcard.Type);
                                UpdateChannelStateUsers(allUsers, ChannelState.nottunable, ch.IdChannel);
                                continue;
                            }

                            if (!cardHandler.Tuner.CanTune(tuningDetail))
                            {
                                //card cannot tune to this channel, so skip it
                                //Log.Info("Controller:    card:{0} type:{1} cannot tune to channel", cardId, tvcard.Type);
                                UpdateChannelStateUsers(allUsers, ChannelState.nottunable, ch.IdChannel);
                                continue;
                            }

                            //check if channel is mapped to this card and that the mapping is not for "Epg Only"
                            bool isChannelMappedToCard = IsChannelMappedToCard(ch, cardHandler.DataBaseCard, channelMapping);
                            if (!isChannelMappedToCard)
                            {
                                UpdateChannelStateUsers(allUsers, ChannelState.nottunable, ch.IdChannel);
                                continue;
                            }

                            if (!tuningDetail.FreeToAir && !cardHandler.DataBaseCard.CAM)
                            {
                                UpdateChannelStateUsers(allUsers, ChannelState.nottunable, ch.IdChannel);
                                continue;
                            }

                            //ok card could be used to tune to this channel
                            //now we check if its free...
                            int decryptLimit = cardHandler.DataBaseCard.DecryptLimit;
                            CheckTransponderAllUsers(ch, allUsers, cards, cardHandler, decryptLimit, cardId, tuningDetail,
                                                     checkTransponders);
                        } //while card end
                    }     //foreach tuningdetail end

                    //only query once
                    if (TSandRecStates == null)
                    {
                        Stopwatch stopwatchTsRec = Stopwatch.StartNew();
                        TSandRecStates = tvController.GetAllTimeshiftingAndRecordingChannels();
                        stopwatchTsRec.Stop();
                        Log.Info("ChannelStates.GetAllTimeshiftingAndRecordingChannels took {0} msec",
                                 stopwatchTsRec.ElapsedMilliseconds);
                    }
                    UpdateRecOrTSChannelStateForUsers(ch, allUsers, TSandRecStates);
                }

                RemoveAllTunableChannelStates(allUsers);
            }
            catch (InvalidOperationException tex)
            {
                Log.Error("ChannelState: Possible race condition occured setting channel states - {0}", tex.StackTrace);
            }
            catch (Exception ex)
            {
                Log.Error("ChannelState: An unknown error occured while setting channel states - {0}\n{1}", ex.Message,
                          ex.StackTrace);
            }
            finally
            {
                stopwatch.Stop();
                Log.Info("ChannelStates.DoSetChannelStates took {0} msec", stopwatch.ElapsedMilliseconds);
            }
        }