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);
      }
    }