'Imports System.Data.BLCommon
Imports Microsoft.Practices.EnterpriseLibrary.Data
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Collections.Generic
Imports System.Xml
Imports System.Configuration
Imports System.Web
Imports CharterDotCom.CommonEntities.Library
Imports CharterDotCom.CommonEntities.Library.Enumerations
Imports CharterDotCom.CommonEntities.Library.EntityMemberServices
'Imports CharterDotCom.CommonEntities.Library.EntityEBSServices
Imports CharterDotCom.CommonEntities.Library.EntitySupport
Imports CharterDotCom.CommonEntities.Library.EntitySearch
Imports CharterDotCom.CommonEntities.Library.EntityWebConfig
'Imports CharterDotCom.CommonEntities.Library.EntityG2BServices
Imports CharterDotCom.WebSite.Library.BLCommon
Imports System.Xml.Serialization

Public Class BLCatalogManager
    Inherits CatalogClient
    ' class level declarations / variables

    Private _FTAID As String
    Private catalog As BLProductCatalog
    Private featureList As Dictionary(Of String, ISubCartItem)
    Private serviceFeatureList As Dictionary(Of String, ServicePlanFeatures)
    Private rules As Rules
    Private UndoStack As Stack(Of Items)
    Private promoCode As Dictionary(Of String, String)      '9/2007 jbm added for 4.1
    Private _message As Notification
    Private _undoremove As Boolean = False
    Private receivers As Dictionary(Of String, BLCommon.Receivers)
    Private configdata_content As XmlNode
    Private configdata_ebs As XmlNode
    Private configdata_member As XmlNode
    Private configdata_g2b As XmlNode


    'Friend CookieID As String

    Public Sub New()

    End Sub
    Public Sub New(ByVal DictionaryOfVariables As Dictionary(Of String, Object))
        If DictionaryOfVariables.ContainsKey("catalog") Then
            If Not (DictionaryOfVariables("catalog") Is Nothing) Then
                Me.catalog = CType(DictionaryOfVariables("catalog"), BLProductCatalog)
            End If
        End If
        If DictionaryOfVariables.ContainsKey("featureList") Then
            If Not (DictionaryOfVariables("featureList") Is Nothing) Then
                Me.featureList = CType(DictionaryOfVariables("featureList"), Dictionary(Of String, ISubCartItem))
            End If
        End If
        If DictionaryOfVariables.ContainsKey("serviceFeatureList") Then
            If Not (DictionaryOfVariables("serviceFeatureList") Is Nothing) Then
                Me.serviceFeatureList = CType(DictionaryOfVariables("serviceFeatureList"), Dictionary(Of String, ServicePlanFeatures))
            End If
        End If
        If DictionaryOfVariables.ContainsKey("rules") Then
            If Not (DictionaryOfVariables("rules") Is Nothing) Then
                Me.rules = CType(DictionaryOfVariables("rules"), Rules)
            End If
        End If
        If DictionaryOfVariables.ContainsKey("UndoStack") Then
            If Not (DictionaryOfVariables("UndoStack") Is Nothing) Then
                Me.UndoStack = CType(DictionaryOfVariables("UndoStack"), Stack(Of Items))
            End If
        End If
        If DictionaryOfVariables.ContainsKey("promoCode") Then
            If Not (DictionaryOfVariables("promoCode") Is Nothing) Then
                Me.promoCode = CType(DictionaryOfVariables("promoCode"), Dictionary(Of String, String))
            End If
        End If
    End Sub



    Public ReadOnly Property ValuesForSetSession() As Dictionary(Of String, Object)
        Get
            Dim VarList As New Dictionary(Of String, Object)
            VarList.Add("catalog", Me.catalog)
            VarList.Add("featureList", Me.featureList)
            VarList.Add("serviceFeatureList", Me.serviceFeatureList)
            VarList.Add("rules", Me.rules)
            VarList.Add("UndoStack", Me.UndoStack)
            VarList.Add("promoCode", Me.promoCode)
            Return VarList
        End Get
    End Property
    Friend Property ProductCatalog() As BLProductCatalog
        Get
            Return catalog
        End Get
        Set(ByVal value As BLProductCatalog)
            catalog = value
        End Set
    End Property

    Private ReadOnly Property sCart() As BLShoppingCart
        Get
            Return CType(catalog.Cart, BLShoppingCart)
        End Get
    End Property

    Protected Overrides Sub PopulateLocalVariables(ByVal trackingID As String)
        Try
            If Not (trackingID Is Nothing) Then
                MyBase.TrackingID = trackingID
                Dim sessionEntry As Object = Session(BLCommon.CatalogManagerKey)
                If Not sessionEntry Is Nothing Then
                    Dim lmanager As New BLCatalogManager(CType(sessionEntry, Dictionary(Of String, Object)))

                    Me.catalog = lmanager.catalog
                    Me.featureList = lmanager.featureList
                    Me.serviceFeatureList = lmanager.serviceFeatureList
                    Me.rules = lmanager.rules
                    Me.UndoStack = lmanager.UndoStack
                    Me.promoCode = lmanager.promoCode
                End If
                'Dim lProviderSection As ProviderSectionHandler = CType(System.Web.HttpContext.Current.Application("ProviderSection"), ProviderSectionHandler)
                'configdata_content = lProviderSection.ProviderData("ContentProvider")
                'configdata_ebs = lProviderSection.ProviderData("EBSServicesProvider")
                'configdata_member = lProviderSection.ProviderData("MemberServicesProvider")
                'configdata_g2b = lProviderSection.ProviderData("G2BServicesProvider")
            End If
        Catch ex As Exception
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        End Try
    End Sub

    '#########################################################
    'MODIFICATION   ROD COPELAND    OCT 6, 2009 ISSUE ID 5382
    '#########################################################
    Public Sub ClearCatalog(ByVal trackID As String)
        catalog = Nothing
        SetSession(CatalogManagerKey, Me.ValuesForSetSession)
    End Sub

#Region "Populate catalog functions"

    ''' <summary>
    ''' Returns an Object of type ICatalog which has Bundles and ServivcePlans.
    ''' If a user is Returning User(cookie information is in Database) populates Cart also.
    ''' </summary>
    ''' <returns>An object of type Icatalog which has Bundles and Service plans</returns>
    ''' <remarks>
    '''  Calls QueryOffersProvider's QueryOffers method, which populates catalog object.
    ''' set's Removable Property to all the features in Serviceplans.
    ''' Feature List is created to use in Grid mode.
    ''' If user is Returning user( already visited site) cart is retrived from Database if persisted.
    ''' Rules will be also populated in provider.
    ''' Before calling this method Account Mangager's Localization or SinIn should be called.
    ''' </remarks>
    Public Overrides Function GetCatalog(ByVal trackID As String) As ICatalog
        Try
            PopulateLocalVariables(trackID)
            If catalog Is Nothing Then
                Dim am As New BLAccountManager(CType(Session(BLCommon.AccountManagerKey), Dictionary(Of String, Object)))

                If am.account.UserType = UserType.Author Then
                    'Retrieve National level catalog
                    Dim objProductcatalog As ProductCatalog

                    Dim objServicePlanList As Dictionary(Of String, ServicePlan)
                    Dim objServicePlanBundleList As Dictionary(Of String, ServicePlan)
                    Dim objBundleList As Dictionary(Of String, Bundle)

                    Dim objOwnerList As OWNERLIST

                    objOwnerList = GetCatalogList("SERVICEPLAN")
                    objServicePlanList = New Dictionary(Of String, ServicePlan)

                    If Not objOwnerList.m_OWNERDATA Is Nothing Then
                        For Each item As OWNERDATA In objOwnerList.m_OWNERDATA
                            objServicePlanList.Add(CStr(item.ID), New ServicePlan(CStr(item.ID), item.Name, item.DESCRIPTION, 0, 0, GWYCategory.Cable, 0, String.Empty, String.Empty, String.Empty, String.Empty, ServiceType.Basic, New Dictionary(Of String, Feature)))
                        Next
                    End If


                    objOwnerList = GetCatalogList("BUNDLE")
                    objServicePlanBundleList = New Dictionary(Of String, ServicePlan)
                    objBundleList = New Dictionary(Of String, Bundle)

                    If Not objOwnerList.m_OWNERDATA Is Nothing Then

                        For Each item As OWNERDATA In objOwnerList.m_OWNERDATA
                            Dim objSubItemList As OWNERLIST = GetCatalogList("BUNDLE-SERVICEPLAN", item.ID)
                            For Each subitem As OWNERDATA In objSubItemList.m_OWNERDATA
                                If Not objServicePlanList(CStr(subitem.ID)) Is Nothing Then
                                    objServicePlanBundleList.Add(CStr(subitem.ID), objServicePlanList(CStr(subitem.ID)))
                                End If
                            Next
                            objBundleList.Add(CStr(item.ID), New Bundle(CStr(item.ID), item.Name, item.DESCRIPTION, 0, 0, 0, String.Empty, String.Empty, String.Empty, String.Empty, objServicePlanBundleList))
                            objServicePlanBundleList = New Dictionary(Of String, ServicePlan)
                        Next

                    End If

                    objProductcatalog = New ProductCatalog(objBundleList, objServicePlanList)
                    catalog = New BLProductCatalog(objProductcatalog)

                    PopulateFeatureList("NATIONAL")

                Else
                    ' user specific catalog

                    'Dim iProvider As IG2BServicesProvider = providerFactory.CreateProvider(Of IG2BServicesProvider)(BLCommon.AssemblyName)
                    Dim iProvider As IG2BServicesProvider = CType(Activator.GetObject(GetType(IG2BServicesProvider), CStr(HttpContext.Current.Application("RemoteURL_G2BServicesProvider"))), IG2BServicesProvider)

                    Dim address As Address = ConvertBLAddressToGwyAddress(CType(am.account.Address, BLAddress))
                    Dim account As BLAccount = am.account
                    If account.UserStatus = UserStatus.Localized OrElse account.UserStatus = UserStatus.Authenticated OrElse account.UserStatus = UserStatus.Identified Then
                        If account.AddressID Is Nothing OrElse account.AddressID = String.Empty Then
                            ' first time request

                            Dim providerRequest As EntityG2BServices.G2BQueryOffersRequest

                            providerRequest = New EntityG2BServices.G2BQueryOffersRequest(address, Nothing, account.AffliateID) ' ConverToGWYLOB(am.account.AvailableLOB))

                            If Not account Is Nothing Then
                                '9/18/2007 Brad Miller - Add population of promoCode for G2B 4.1
                                providerRequest.RegionID = account.RegionID
                                providerRequest.KMAID = account.KMAID
                                providerRequest.BillingStationID = account.BillingCode
                                If Not account.FTA Is Nothing Then
                                    providerRequest.FTA = account.FTA
                                End If
                                If Not Me.promoCode Is Nothing Then
                                    providerRequest.PromotionCode = Me.promoCode
                                End If
                            End If

                            Dim providerResponse As EntityG2BServices.G2BQueryOffersResponse
                            providerResponse = CType(iProvider.QueryOffers(providerRequest), EntityG2BServices.G2BQueryOffersResponse)

                            If Not providerResponse Is Nothing Then
                                If providerResponse.Exception Then
                                    BLCommon.LogException(New ApplicationException("Catalog Manager: Cannot retrive Catalog for Address : " + account.Address.Street1 + "," + account.Address.Street2 + "," + account.Address.Zip), ExceptionSeverity.Catastrophic)
                                    Return Nothing
                                End If
                                account.TrackingID = providerResponse.TrackingID
                                account.MSOID = providerResponse.MSOID

                                If providerResponse.ProductCatalog Is Nothing Then
                                    Return Nothing
                                End If

                                catalog = New BLProductCatalog(providerResponse.ProductCatalog)
                                ' rules required to set removable property to find the base (priority) service plan in a category
                                rules = providerResponse.Rules


                                Call BuildGeneralQuestionList(providerResponse, account)

                            Else
                                BLCommon.LogException(New ApplicationException("Cannot retrive Catalog for Address : " + account.Address.Street1 + "," + account.Address.Street2 + "," + account.Address.Zip), ExceptionSeverity.Catastrophic)
                                Return Nothing
                            End If

                        Else
                            ' this is a resubmit

                            ''ToDo: comment Out these 2 lines once localization is fixed
                            'account.TrackingID = 614541366
                            'account.MSOID = 1011000079

                            Dim providerRequest As EntityG2BServices.G2BQueryOffersResubmitRequest
                            providerRequest = New EntityG2BServices.G2BQueryOffersResubmitRequest(account.TrackingID, account.MSOID, account.AddressID, account.AffliateID)

                            If Not account Is Nothing Then
                                providerRequest.RegionID = account.RegionID
                                providerRequest.KMAID = account.KMAID
                                providerRequest.BillingStationID = account.BillingCode
                                If Not account.FTA Is Nothing Then
                                    providerRequest.FTA = account.FTA
                                End If
                            End If

                            Dim providerResponse As EntityG2BServices.G2BQueryOffersResubmitResponse
                            providerResponse = CType(iProvider.QueryOffersResubmit(providerRequest), EntityG2BServices.G2BQueryOffersResubmitResponse)

                            If Not providerResponse Is Nothing Then
                                If providerResponse.Exception Then
                                    BLCommon.LogException(New ApplicationException("Cannot retrive Catalog for Address : " + account.Address.Street1 + "," + account.Address.Street2 + "," + account.Address.Zip), ExceptionSeverity.Catastrophic)
                                    Return Nothing
                                Else
                                    If Not providerResponse.ProductCatalog Is Nothing Then
                                        catalog = New BLProductCatalog(providerResponse.ProductCatalog)
                                    Else
                                        Return Nothing
                                    End If
                                End If


                                ' rules required to set removable property( to find the base( priority) service plan in a category
                                'TODo: uncomment this line once proider response entity is changed
                                'rules = providerResponse.Rules
                            Else
                                BLCommon.LogException(New ApplicationException("Cannot retrive Catalog for Address : " + account.Address.Street1 + "," + account.Address.Street2 + "," + account.Address.Zip), ExceptionSeverity.Catastrophic)
                                Return Nothing
                            End If

                        End If

                        SetRemovableProperty()
                        ''If Not contentparams Is Nothing Then
                        ''  Dim contentProvider As IContentProvider = CType(Activator.GetObject(GetType(CommonProviderInterfaces.IContentProvider), CStr(HttpContext.Current.Application("RemoteURL_ContentProvider"))), CommonProviderInterfaces.IContentProvider)
                        ''  Dim dtContent As DataTable = contentProvider.GetMultipleContent(contentparams)
                        ''  If Not dtContent Is Nothing Then
                        ''    catalogcontent = New Dictionary(Of String, String)
                        ''    For Each dr As DataRow In dtContent.Rows
                        ''      catalogcontent.Add(CStr(dr.Item(0)), CStr(dr.Item(1)))
                        ''    Next
                        ''  End If
                        ''End If
                        PopulateFeatureList()
                        If account.IsReturningUser Then
                            ' returning user , populate shopping cart
                            PopulateCartIfPersisted(am)
                        End If
                    End If
                End If
                SetSession(CatalogManagerKey, Me.ValuesForSetSession)
                SetSession(AccountManagerKey, am.ValuesForSetSession)
            End If

            Return catalog

        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot get Product Catalog", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try

    End Function

    Private Sub BuildGeneralQuestionList(ByVal providerResponse As EntityG2BServices.G2BQueryOffersResponse, ByVal account As BLAccount)

        '#############################################################################
        '10/24/2007 Brad Miller
        'BUILD A LIST OF NEW AND EXISTING CUSTOMERS IN THE SAME COLLECTION WITH A 
        'DISTINCTION OF THE CUSTOMERTYPE TO SHOW DIFF BETWEEN THE QUESTIONS TO ASK 
        'EACH CUSTOMER
        '#############################################################################


        '##############################################################################
        'BUILD THE LIST FOR THE NEW CUSTOMERS 
        '##############################################################################
        If providerResponse.CustomerAuthFieldDefinition.NewCustomer IsNot Nothing Then
            account.G2B_AuthQuestion = New Dictionary(Of String, IAccount.IAuthQuestion)
            For iItem As Integer = 0 To providerResponse.CustomerAuthFieldDefinition.NewCustomer.Count - 1
                If providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth IsNot Nothing Then
                    For iCustAuth As Integer = 0 To providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth.Count - 1

                        Dim objAuthQuestion As New BLG2BAuthQuestion
                        objAuthQuestion.CustomerType = CustomerType.NewCustomer
                        objAuthQuestion.QuestionID = providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth(iCustAuth).authFieldID
                        objAuthQuestion.IsBoolean = providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth(iCustAuth).booleanField
                        objAuthQuestion.QuestionDescription = providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth(iCustAuth).description
                        objAuthQuestion.MaxLen = providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth(iCustAuth).maxLen
                        If Not (providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth(iCustAuth).name Is Nothing) Then
                            objAuthQuestion.QuestionName = providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth(iCustAuth).name().Trim().ToUpper()
                        End If
                        objAuthQuestion.AuthQuestionType = eAuthQuestionType.Custom
                        objAuthQuestion.IsMasked = providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).CustomAuth(iCustAuth).privateField

                        '##############################################################################
                        'THIS QUESTION CHECK IS FOR DETERMINING IF THE USER SUCESSFULLY AUTHENTICATED 
                        'VIA THE MEMBER SERVICE WEB SERVICE VIA THE MS PROVIDER
                        '##############################################################################
                        If Not (objAuthQuestion.QuestionID Is Nothing) Then
                            If objAuthQuestion.QuestionID.Trim() = "300" Then
                                If account.UserStatus = UserStatus.Authenticated Then
                                    objAuthQuestion.UserResponded = True
                                    objAuthQuestion.AnswerFromUser = "true"
                                End If
                            End If
                        End If

                        If Not account.G2B_AuthQuestion.ContainsKey(objAuthQuestion.QuestionID) Then
                            account.G2B_AuthQuestion.Add(objAuthQuestion.QuestionID, objAuthQuestion)
                        End If

                    Next
                End If

                If providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).StandardAuth IsNot Nothing Then
                    For iStdAuth As Integer = 0 To providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).StandardAuth.Count - 1
                        Dim objAuthQuestion As New BLG2BAuthQuestion

                        objAuthQuestion.QuestionID = providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).StandardAuth(iStdAuth).ToString()

                        objAuthQuestion.QuestionName = providerResponse.CustomerAuthFieldDefinition.NewCustomer(iItem).StandardAuth(iStdAuth).ToString().Trim().ToUpper()

                        objAuthQuestion.AuthQuestionType = eAuthQuestionType.Standard

                        If Not account.G2B_AuthQuestion.ContainsKey(objAuthQuestion.QuestionID) Then
                            account.G2B_AuthQuestion.Add(objAuthQuestion.QuestionID, objAuthQuestion)
                        End If
                    Next
                End If
            Next
        End If





        '##############################################################################
        'BUILD THE LIST FOR THE EXISTING CUSTOMERS
        '##############################################################################
        If providerResponse.CustomerAuthFieldDefinition.ExistingCustomer IsNot Nothing Then
            If (account.G2B_AuthQuestion Is Nothing) Then
                account.G2B_AuthQuestion = New Dictionary(Of String, IAccount.IAuthQuestion)
            End If

            For iItem As Integer = 0 To providerResponse.CustomerAuthFieldDefinition.ExistingCustomer.Count - 1
                If providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth IsNot Nothing Then
                    For iCustAuth As Integer = 0 To providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth.Count - 1

                        Dim objAuthQuestion As New BLG2BAuthQuestion
                        objAuthQuestion.CustomerType = CustomerType.ExistingCustomer
                        objAuthQuestion.QuestionID = providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth(iCustAuth).authFieldID
                        objAuthQuestion.IsBoolean = providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth(iCustAuth).booleanField
                        objAuthQuestion.QuestionDescription = providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth(iCustAuth).description
                        objAuthQuestion.MaxLen = providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth(iCustAuth).maxLen
                        If Not (providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth(iCustAuth).name Is Nothing) Then
                            If Not (providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth(iCustAuth).name() Is Nothing) Then
                                objAuthQuestion.QuestionName = providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth(iCustAuth).name().Trim().ToUpper()
                            End If
                        End If
                        objAuthQuestion.AuthQuestionType = eAuthQuestionType.Custom
                        objAuthQuestion.IsMasked = providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).CustomAuth(iCustAuth).privateField

                        '##############################################################################
                        'THIS QUESTION CHECK IS FOR DETERMINING IF THE USER SUCESSFULLY AUTHENTICATED 
                        'VIA THE MEMBER SERVICE WEB SERVICE VIA THE MS PROVIDER
                        '##############################################################################
                        If Not (objAuthQuestion.QuestionID Is Nothing) Then
                            If objAuthQuestion.QuestionID.Trim() = "300" Then
                                If account.UserStatus = UserStatus.Authenticated Then
                                    objAuthQuestion.UserResponded = True
                                    objAuthQuestion.AnswerFromUser = "true"
                                End If
                            End If
                        End If

                        If Not account.G2B_AuthQuestion.ContainsKey(objAuthQuestion.QuestionID) Then
                            account.G2B_AuthQuestion.Add(objAuthQuestion.QuestionID, objAuthQuestion)
                        End If
                    Next
                End If

                If providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).StandardAuth IsNot Nothing Then
                    For iStdAuth As Integer = 0 To providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).StandardAuth.Count - 1
                        Dim objAuthQuestion As New BLG2BAuthQuestion

                        objAuthQuestion.QuestionID = providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).StandardAuth(iStdAuth).ToString()

                        objAuthQuestion.QuestionName = providerResponse.CustomerAuthFieldDefinition.ExistingCustomer(iItem).StandardAuth(iStdAuth).ToString().Trim().ToUpper()


                        objAuthQuestion.AuthQuestionType = eAuthQuestionType.Standard

                        If Not account.G2B_AuthQuestion.ContainsKey(objAuthQuestion.QuestionID) Then
                            account.G2B_AuthQuestion.Add(objAuthQuestion.QuestionID, objAuthQuestion)
                        End If
                    Next
                End If
            Next
        End If



    End Sub


    ''' <summary>
    ''' Returns a Dictionary with key as ID and all available features.
    ''' </summary>
    ''' <returns>Retrns the list of Features </returns>
    ''' <remarks>Loops through all the service plans in catalog and 
    ''' adds features from each service plan to the features list if its not already added. 
    ''' Also creates ServiceFeatureList which is required to find a service plan when a feature is added in Grid mode.
    ''' </remarks>
    Public Overrides Function GetFeatures(ByVal trackID As String) As Dictionary(Of String, ISubCartItem)

        Try
            PopulateLocalVariables(trackID)
            PopulateFeatureList()
            Return featureList
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot get Features", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try
    End Function

    Private Function GetCatalogList(ByVal Code As String, Optional ByVal PlayBookID As String = Nothing) As OWNERLIST
        'Function level variables which are destroyed in the Finally block
        Dim objRoot As New XmlRootAttribute("OWNERLIST")
        Dim ownerlist As Dictionary(Of Integer, String)
        'Get object to be returned to UI layer
        Dim objOwnerList As OWNERLIST
        'Get serializer for De-serializing content xml to Content object
        Dim objXMLSerializer_Content As XmlSerializer

        Try
            Dim strtemp As String
            'Currently test parameters are used, needs to change to refer to actual parameters
            'Dim contentProvider As IContentProvider = providerFactory.CreateProvider(Of IContentProvider)(BLCommon.AssemblyName)
            Dim contentProvider As IContentProvider = CType(Activator.GetObject(GetType(IContentProvider), CStr(HttpContext.Current.Application("RemoteURL_ContentProvider"))), IContentProvider)
            Select Case Code.ToUpper()
                Case "SERVICEPLAN"
                    strtemp = contentProvider.GetServicePlanList()
                Case "BUNDLE"
                    strtemp = contentProvider.GetBundleList()
                Case "FEATURE"
                    strtemp = contentProvider.GetFeatureList()
                Case "EPC"
                    strtemp = contentProvider.GetEPCIDList(PlayBookID)
                Case "BUNDLE-SERVICEPLAN"
                    strtemp = contentProvider.GetServicePlanIDByBundleList(PlayBookID)
            End Select


            'Load the string reader with the XML string returned by Data Access layer
            Dim objReader As New System.IO.StringReader(strtemp)

            'Instantiate XML serializer of the corresponding content object type
            objXMLSerializer_Content = New XmlSerializer(GetType(OWNERLIST), objRoot)

            'De-serialize the XML data onto an instance
            objOwnerList = CType(objXMLSerializer_Content.Deserialize(objReader), OWNERLIST)

            'return the object to UI layer
            Return objOwnerList

        Catch ex As Exception
            'BLCommon.LogException(ex, ExceptionSeverity.High)
            Throw
        Finally
            ownerlist = Nothing
            objRoot = Nothing
        End Try
    End Function


    Private Sub PopulateFeatureList(Optional ByVal providerFactory As String = Nothing)
        Try
            If featureList Is Nothing Then
                If Not providerFactory Is Nothing Then

                    'Retrieve National level feature list
                    featureList = New Dictionary(Of String, ISubCartItem)

                    Dim objOwnerList As OWNERLIST

                    objOwnerList = GetCatalogList("FEATURE")
                    If Not objOwnerList.m_OWNERDATA Is Nothing Then

                        For Each item As OWNERDATA In objOwnerList.m_OWNERDATA
                            Dim obj As New BLFeature(New Feature(CStr(item.ID), item.Name, item.DESCRIPTION, _
                                GWYCategory.Cable, ServiceType.Basic, FeatureCategory.VideoFeature, _
                                GWYFeatureType.IsIncluded, 0, 0, PriceFrequency.Monthly, True, _
                                New Dictionary(Of String, Feature), 0, 0, 0, 0, String.Empty, 0, GwyCustomizationInputType.Number))
                            featureList.Add(obj.ID, CType(obj, ISubCartItem))
                        Next

                    End If
                Else
                    featureList = New Dictionary(Of String, ISubCartItem)
                    'Dim strTemp As String

                    For Each sp As BLServicePlan In catalog.ServicePlans.Values
                        ' sp = CType(item, ServicePlan)
                        For Each f As ISubCartItem In sp.Features.Values
                            AddToServiceFeatures(f, sp.ID)
                            AddToFeatureList(f)
                            For Each ch As ISubCartItem In f.Children.Values
                                AddToFeatureList(ch)
                            Next
                        Next
                        ' ''Assign catalog content
                        ''If Not catalogcontent Is Nothing AndAlso catalogcontent.TryGetValue(sp.gwySP.ID, strTemp) Then
                        ''  sp.gwySP.MarketingInfo = strTemp
                        ''End If
                    Next
                    ' ''Assign catalog content
                    ''For Each b As BLBundle In catalog.Bundles.Values
                    ''  If Not catalogcontent Is Nothing AndAlso catalogcontent.TryGetValue(b.gwyBundle.ID, strTemp) Then
                    ''    b.gwyBundle.MarketingInfo = strTemp
                    ''  End If
                    ''Next
                End If

                SetSession(CatalogManagerKey, Me.ValuesForSetSession)
            End If


        Catch ex As Exception
            Throw
        End Try

    End Sub

    ' checks to see if a particular category of service exists in the specified area. 
    Private Function ServiceAvailable(ByVal type As ServiceType) As Boolean
        'Dim am As AccountManager = AccountManager.Instance
        'If am.account.AvailableLOB.Contains(type) Then Return True
        Return True
    End Function

    Private Sub SetRemovableProperty()
        'Dim dtContent As DataTable
        'Dim dsContent As DataSet

        Try
            'dtContent = New DataTable("ContentKey")

            'With dtContent
            '  .Columns.Add("UserControl", Type.GetType("System.String"))
            '  .Columns.Add("Owner", Type.GetType("System.String"))
            '  .Columns.Add("OwnerType", Type.GetType("System.String"))
            '  .Columns.Add("Locale", Type.GetType("System.String"))
            '  .Columns.Add("Region", Type.GetType("System.String"))
            '  .Columns.Add("KMA", Type.GetType("System.String"))
            '  .Columns.Add("billingstation", Type.GetType("System.String"))
            '  .Columns.Add("fta", Type.GetType("System.String"))
            'End With

            Dim baseFeatures As List(Of String)
            Dim featuresByCategory As New Dictionary(Of Category, List(Of String))

            ' bundles
            For Each b As BLBundle In catalog.Bundles.Values
                For Each sp As BLServicePlan In b.ServicePlans.Values
                    SetRemovableForServicePlan(sp, baseFeatures, featuresByCategory)
                Next
                ''Dim dar As DataRow = dtContent.NewRow()
                ''dar.Item("UserControl") = "Offer"
                ''dar.Item("Owner") = b.gwyBundle.ID
                ''dar.Item("OwnerType") = "1"
                ''dar.Item("Locale") = "1"
                ''If Not intRegionID = 0 Then dar.Item("Region") = intRegionID
                ''If Not intKMAId = 0 Then dar.Item("KMA") = intKMAId
                ''If Not intBillingStationID = 0 Then dar.Item("billingstation") = intBillingStationID
                ''If Not strFTAID Is Nothing Then dar.Item("fta") = strFTAID
                ''dtContent.Rows.Add(dar)
            Next
            For Each sp As BLServicePlan In catalog.ServicePlans.Values
                SetRemovableForServicePlan(sp, baseFeatures, featuresByCategory)
                ''Dim dar As DataRow = dtContent.NewRow()
                ''dar.Item("UserControl") = "Offer"
                ''dar.Item("Owner") = sp.gwySP.ID
                ''dar.Item("OwnerType") = "2"
                ''dar.Item("Locale") = "1"
                ''If Not intRegionID = 0 Then dar.Item("Region") = intRegionID
                ''If Not intKMAId = 0 Then dar.Item("KMA") = intKMAId
                ''If Not intBillingStationID = 0 Then dar.Item("billingstation") = intBillingStationID
                ''If Not strFTAID Is Nothing Then dar.Item("fta") = strFTAID
                ''dtContent.Rows.Add(dar)
            Next
            ''If dtContent.Rows.Count > 0 Then
            ''  dsContent = New DataSet("Content")
            ''  dsContent.Tables.Add(dtContent)
            ''  contentparams = dsContent.GetXml()
            ''End If
        Catch ex As Exception
            Throw New ApplicationException("Exception setting removable property for features", ex)
        Finally
            ''dsContent = Nothing
            ''dtContent = Nothing
        End Try
    End Sub

    '9/18/2007 Brad Miller - Added for G2B 4.1
    Public Sub PopulatePromoCodes(ByVal pc As String)
        If promoCode Is Nothing Then
            promoCode = New Dictionary(Of String, String)
        End If
        If Not promoCode.ContainsKey(pc) Then
            promoCode.Add(pc, pc)
        End If
    End Sub
    Private Sub SetRemovableForServicePlan(ByVal sp As BLServicePlan, ByVal basefeatures As List(Of String), ByVal featuresByCategory As Dictionary(Of Category, List(Of String)))
        If featuresByCategory.ContainsKey(sp.Category) Then
            ' base feature list for this category is alreay created
            basefeatures = featuresByCategory(sp.Category)
        Else
            ' base feature list for this category is not created, so create
            basefeatures = GetBasePlanFeaturesForCategory(sp.Category)
            featuresByCategory.Add(sp.Category, basefeatures)
        End If
        ' features
        For Each f As BLFeature In sp.Features.Values
            If f.Choices Is Nothing OrElse f.Choices.Count = 0 Then
                ' default features
                If basefeatures.Contains(f.ID) Then
                    ' this feature is one of the default features for base service plan in this category
                    f.ISRemovable = False
                Else
                    f.ISRemovable = True
                End If
            Else
                ' this is a place holder.
                ' place holders are never removable.
                f.ISRemovable = False
                For Each c As BLFeature In f.Choices.Values
                    ' thse are choices of a place holder. these are always( if selected) removable
                    c.ISRemovable = True
                Next
            End If
        Next
    End Sub

    'creates a list of features, which are default features of a base service plan.
    Private Function GetBasePlanFeaturesForCategory(ByVal category As Category) As List(Of String)
        Dim features As New List(Of String)
        ' for HSD category all features are base features and should not be removable
        If category.Equals(category.HSD) Then
            For Each sp As BLServicePlan In catalog.ServicePlans.Values
                If sp.Category.Equals(category.HSD) Then
                    ' if category is HSD then all the deafault\included features should be added
                    For Each f As BLFeature In sp.Features.Values
                        'add all default features of this service plan to list
                        If f.Choices Is Nothing OrElse f.Choices.Count = 0 Then
                            features.Add(f.ID)
                        End If
                    Next
                End If
            Next
        Else
            Dim cableSPs As New List(Of String)
            For Each si As ISubCartItem In catalog.ServicePlans.Values
                If si.Category = category.Cable Then
                    cableSPs.Add(si.ID)
                End If
            Next

            ' find the base service plan for this category
            'Dim spID As String = rules.GetPriorityServicePlan(BLCommon.ConvertToGWYCategory(category))
            Dim spID As String = rules.GetPriorityServicePlan(cableSPs)
            If catalog.ServicePlans.ContainsKey(spID) Then
                Dim sp As BLServicePlan = DirectCast(catalog.ServicePlans(spID), BLServicePlan)
                'add each of the default features of this service plan to list
                For Each f As BLFeature In sp.Features.Values
                    If f.Choices Is Nothing OrElse f.Choices.Count = 0 Then
                        ' these are the default features
                        features.Add(f.ID)
                    End If
                Next
            End If
        End If
        Return features
    End Function

    Private Function GetFeatureCategory(ByVal c As GWYCategory) As FeatureCategory
        Select Case c
            Case GWYCategory.Cable
                Return FeatureCategory.VideoFeature
            Case GWYCategory.HSD
                Return FeatureCategory.DataFeature
            Case GWYCategory.Telephoney
                Return FeatureCategory.VoiceFeature
            Case Else
                Return FeatureCategory.Other
        End Select
    End Function

#End Region

#Region "Cart related functions"

    Friend Sub ClearShoppingCart(ByVal trackingID As String)
        Try
            'PopulateLocalVariables(trackingID)
            ' Dim cm As New BLCatalogManager(CType(Session(CatalogManagerKey), Dictionary(Of String, Object)))
            ' Dim catalog As BLProductCatalog = cm.ProductCatalog
            catalog.ClearCart()
            RefreshFeatureList()
            ' SetSession(CatalogManagerKey, cm.ValuesForSetSession)
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot Clear cart", ex)
            BLCommon.LogException(aex, ExceptionSeverity.High)
            Throw aex
        End Try
    End Sub

    ''' <summary>
    '''  Adds Bundles and Service Plans to the shopping cart.
    ''' </summary>
    ''' <param name="itemID"> ID of BUndle/ Service Plan that should be added to cart</param>
    ''' <param name="trackID">TrackingID of he request</param>
    ''' <remarks> 
    ''' From given ItemID checks to see if it a bundle or service plan, and calls AddItemToCart with appropriate item.
    ''' Dynamic Bundling will be done.
    ''' UndoStack will be cleared.
    ''' Refreshes FeatureList.
    ''' Invokes Notify delegate about any unexpected changes to ShoppingCart.
    ''' Updates Shopping cart price.
    ''' After all the Chages are done adds CatalogManager to session.
    ''' </remarks>

    Public Overrides Function AddCartItem(ByVal trackID As String, ByVal itemID As String) As INotification
        Dim item As ICartItem
        Try
            PopulateLocalVariables(trackID)
            If catalog.Cart.Submitted Then
                ClearShoppingCart(trackID)
                CType(catalog.Cart, BLShoppingCart).OrderSubmitted = False
            End If
            'if item type is bundle then, add all the children(service plans) to cart insted of bundle itself
            If catalog.Bundles.ContainsKey(itemID) Then
                item = catalog.Bundles(itemID)

                ' set cart notification message
                _message = New Notification(NotificationAction.Add, item.Name, NotificationCode.Success)

                If Not catalog.Cart.CartItems Is Nothing Then
                    For Each ci As ICartItem In catalog.Cart.CartItems.Values
                        If ci.Type = ItemType.Bundle Then
                            For Each si As BLServicePlan In ci.Children.Values
                                For Each subItem As ISubCartItem In item.Children.Values
                                    If si.ID = subItem.ID Then
                                        UpdateSelectedChoices(si, CType(subItem, ICartItem))
                                        Exit For
                                    End If
                                Next
                            Next
                            RemoveCartItem(trackID, ci.ID)
                            Exit For
                        End If
                    Next
                End If

                For Each subItem As ISubCartItem In item.Children.Values
                    AddItemToCart(catalog.ServicePlans(subItem.ID))
                Next

            Else
                If catalog.ServicePlans.ContainsKey(itemID) Then
                    item = catalog.ServicePlans(itemID)

                    ' set cart notification message
                    _message = New Notification(NotificationAction.Add, item.Name, NotificationCode.Success)

                    AddItemToCart(item)

                End If
            End If

            ' When an item is added clear un do stack
            ClearUnDoStack()

            RefreshFeatureList()
            'To update prices
            sCart.UpdateCartItemsPrice()

            SetSession(CatalogManagerKey, Me.ValuesForSetSession)

            Return _message

        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot add item to cart", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try

        Return Nothing
    End Function

    Private Sub AddItemToCart(ByVal item As ICartItem, Optional ByVal userSelectionList As Dictionary(Of String, CartSelections) = Nothing, Optional ByVal doDynamicBundle As Boolean = True)
        Dim cartItemsWithcategory As Dictionary(Of String, CartSelections)
        'Commented user selection logic as every cart item is user selected    
        Dim objCartSelection As CartSelections
        Dim objServicePlan As BLServicePlan

        If userSelectionList Is Nothing Then
            cartItemsWithcategory = GetCartItemsWithcategory()
        Else
            cartItemsWithcategory = userSelectionList
        End If

        If Not cartItemsWithcategory.ContainsKey(item.ID) Then

            objCartSelection.Category = item.Category
            objCartSelection.FeatureType = FeatureType.NotSpecified

            cartItemsWithcategory.Add(item.ID, objCartSelection)
        End If

        If Not catalog.Cart.CartItems Is Nothing Then
            If item.Type = ItemType.ServicePlan Then
                CheckForCategory(cartItemsWithcategory, item)
            End If
        End If

        sCart.AddCartItem(item)
        catalog.Refresh(item, False, True, cartItemsWithcategory)

        'RefreshFeatureList(item)

        If doDynamicBundle Then
            DynamicBundle(item, cartItemsWithcategory)
        End If

        'RefreshFeatureList(item)



    End Sub

    ''' <summary>
    ''' Adds a Feature to Shopping Cart.
    ''' </summary>
    ''' <param name="itemID">ID of feature that should be added to cart.</param>
    ''' <param name="trackID">TrackingID of he request</param>
    ''' <remarks>
    ''' Finds appropriate service plan based on the current selection and the existing items in the cart by calling FindServicePlan method.
    ''' Adds the ServicePlan found in above method to cart. 
    ''' selected item will be added as sub item to the service plan.
    ''' If there is a change in Service plan with current selections Carries any customization selections to new ServicePlan.
    ''' Applies Dynamic Bundling.
    ''' UndoStack will be cleared.
    ''' Refreshes FeatureList.
    ''' Invokes Notify delegate about any unexpected changes to ShoppingCart.
    ''' Updates Shopping cart price.
    ''' After all the Chages are done adds CatalogManager to session.
    ''' </remarks>
    Public Overrides Function AddSubCartItemWithParent(ByVal trackID As String, ByVal itemID As String, ByVal ParentID As String) As INotification
        Dim receiverLogic As Boolean = False
        Dim item As ISubCartItem
        If receivers Is Nothing Then receivers = GenerateReceivers()
        Try
            If (ParentID Is Nothing) Then
                receiverLogic = False
            Else
                If Not receivers.ContainsKey(ParentID) Then
                    receiverLogic = False
                Else
                    Select Case receivers(ParentID)
                        Case BLCommon.Receivers.HDTV_OR_DVR_SERVICE, BLCommon.Receivers.HDTV_TIER
                            receiverLogic = False
                        Case Else
                            Select Case receivers(itemID)
                                Case BLCommon.Receivers.DVR_MULTI, BLCommon.Receivers.HD_MULTI, BLCommon.Receivers.HD_EQUIP_2, BLCommon.Receivers.EQUIP_2
                                    receiverLogic = False
                                Case Else
                                    receiverLogic = True
                            End Select
                    End Select
                End If

            End If

            If Not receiverLogic Then
                PopulateLocalVariables(trackID)
                ' returning after submitting order
                If catalog.Cart.Submitted Then
                    ClearShoppingCart(trackID)
                    CType(catalog.Cart, BLShoppingCart).OrderSubmitted = False
                End If

                If featureList.TryGetValue(itemID, item) Then

                    ' set cart notification message
                    _message = New Notification(NotificationAction.Add, item.Name, NotificationCode.Success)
                    If ParentID Is Nothing Then
                        AddSubItemToCart(item)
                    Else
                        AddSubItemToCart_Checkout(item)
                    End If

                    Return _message

                End If
            Else
                PopulateLocalVariables(trackID)
                If featureList.TryGetValue(itemID, item) Then

                    ' set cart notification message
                    _message = New Notification(NotificationAction.Add, item.Name, NotificationCode.Success)
                    AddSubItemToCart(item, ParentID)

                    Return _message

                End If
            End If
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot add feature to Cart")
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try

        Return Nothing
    End Function

    Private Sub AddSubItemToCart(ByVal item As ISubCartItem)
        If Not item Is Nothing Then
            Dim objCartSelection As CartSelections
            Dim sp As BLServicePlan
            Dim cartItemsWithCategory As Dictionary(Of String, CartSelections)
            cartItemsWithCategory = GetCartItemsWithcategory()
            If cartItemsWithCategory Is Nothing Then
                cartItemsWithCategory = New Dictionary(Of String, CartSelections)
            End If

            objCartSelection.Category = item.Category
            objCartSelection.FeatureType = item.FeatureType

            If Not cartItemsWithCategory.ContainsKey(item.ID) Then cartItemsWithCategory.Add(item.ID, objCartSelection)

            Dim strRemovedFeatureID As String = RemoveConflictingFeatures(item.ID, cartItemsWithCategory)
            sp = FindServicePlan(item.Category, cartItemsWithCategory)

            If Not DirectCast(catalog.Cart, BLShoppingCart).ContainsThisKey(sp.ID) Then
                ' this service plan is not in cart, new service plan
                ' set cart notification message
                _message.SetMessageResult(String.Empty, sp.Name, NotificationCode.NewServicePlan, NotificationSeverity.IsMessage)

            End If

            If Not strRemovedFeatureID Is Nothing AndAlso Not sp Is Nothing Then
                Dim objRemovedfeature As BLFeature = FindOption(sp.ID, strRemovedFeatureID)
                If Not objRemovedfeature Is Nothing Then
                    UpdateSelectedChoices(objRemovedfeature, strRemovedFeatureID, False, cartItemsWithCategory)
                End If
            End If
            'TODo: review this
            Dim objFeature As BLFeature = FindOption(sp.ID, item.ID)
            If Not objFeature Is Nothing Then
                Dim strTemp As String = UpdateSelectedChoices(objFeature, item.ID, True, cartItemsWithCategory, sp)
                objCartSelection = cartItemsWithCategory(item.ID)
                objCartSelection.FeatureType = FeatureType.IsOptional
                cartItemsWithCategory(item.ID) = objCartSelection
                If Not strTemp Is Nothing Then
                    cartItemsWithCategory.Add(strTemp, objCartSelection)
                End If
            End If

            AddItemToCart(sp, cartItemsWithCategory)

            RefreshFeatureList()
            'To update prices
            sCart.UpdateCartItemsPrice()

            ' when an item is added uoDo remove should be set to false and lcear stack
            ClearUnDoStack()

            SetSession(CatalogManagerKey, Me.ValuesForSetSession)

        End If

    End Sub

    Private Sub AddSubItemToCart_Checkout(ByVal item As ISubCartItem)
        If Not item Is Nothing Then
            Dim objCartSelection As CartSelections
            Dim sp As BLServicePlan
            Dim cartItemsWithCategory As Dictionary(Of String, CartSelections)
            cartItemsWithCategory = GetCartItemsWithcategory()
            If cartItemsWithCategory Is Nothing Then
                cartItemsWithCategory = New Dictionary(Of String, CartSelections)
            End If

            objCartSelection.Category = item.Category
            objCartSelection.FeatureType = item.FeatureType

            If Not cartItemsWithCategory.ContainsKey(item.ID) Then cartItemsWithCategory.Add(item.ID, objCartSelection)

            For Each objitem As ICartItem In catalog.Cart.CartItems.Values
                If objitem.Type = ItemType.Bundle Then
                    For Each objsubitem As ISubCartItem In objitem.Children.Values
                        If objsubitem.Category = item.Category Then
                            sp = CType(objsubitem, BLServicePlan)
                            Exit For
                        End If
                    Next
                Else
                    If objitem.Category = item.Category Then
                        sp = CType(objitem, BLServicePlan)
                        Exit For
                    End If
                End If
            Next


            Dim objFeature As BLFeature = FindOption(sp.ID, item.ID)
            If Not objFeature Is Nothing Then
                Dim strTemp As String = UpdateSelectedChoices(objFeature, item.ID, True, cartItemsWithCategory, sp)
                objCartSelection = cartItemsWithCategory(item.ID)
                objCartSelection.FeatureType = FeatureType.IsOptional
                cartItemsWithCategory(item.ID) = objCartSelection
                If Not strTemp Is Nothing Then
                    cartItemsWithCategory.Add(strTemp, objCartSelection)
                End If
            End If
            catalog.Refresh(sp, False, True, cartItemsWithCategory)

            RefreshFeatureList()
            'To update prices
            sCart.UpdateCartItemsPrice()

            ' when an item is added uoDo remove should be set to false and lcear stack
            ClearUnDoStack()

            SetSession(CatalogManagerKey, Me.ValuesForSetSession)

        End If

    End Sub

    Private Sub AddSubItemToCart(ByVal item As ISubCartItem, ByVal parentID As String)
        If Not item Is Nothing Then
            Dim objCartSelection As CartSelections
            Dim sp As BLServicePlan
            Dim cartItemsWithCategory As Dictionary(Of String, CartSelections)
            cartItemsWithCategory = GetCartItemsWithcategory()
            If cartItemsWithCategory Is Nothing Then
                cartItemsWithCategory = New Dictionary(Of String, CartSelections)
            End If

            objCartSelection.Category = item.Category
            objCartSelection.FeatureType = item.FeatureType

            If Not cartItemsWithCategory.ContainsKey(item.ID) Then cartItemsWithCategory.Add(item.ID, objCartSelection)


            For Each objitem As ICartItem In catalog.Cart.CartItems.Values
                If objitem.Type = ItemType.Bundle Then
                    For Each objsubitem As ISubCartItem In objitem.Children.Values
                        If objsubitem.Category = item.Category Then
                            sp = CType(objsubitem, BLServicePlan)
                            Exit For
                        End If
                    Next
                Else
                    If objitem.Category = item.Category Then
                        sp = CType(objitem, BLServicePlan)
                        Exit For
                    End If
                End If
            Next

            Dim subitem As ISubCartItem
            Dim f As BLFeature

            If sp.Features.TryGetValue(BLCommon.GetKey(BLCommon.Receivers.TV_NUMBERS, receivers), subitem) Then
                f = DirectCast(subitem, BLFeature)
                Dim strTemp As String = UpdateTVOptions(sp, receivers, f.SelectedChoices, parentID, item.ID)
                objCartSelection = cartItemsWithCategory(item.ID)
                objCartSelection.FeatureType = FeatureType.IsOptional
                cartItemsWithCategory(item.ID) = objCartSelection
                If Not strTemp Is Nothing Then
                    cartItemsWithCategory.Add(strTemp, objCartSelection)
                End If
                If f.SelectedChoices.Count > 0 Then
                    Dim cartsel As CartSelections
                    cartsel.Category = f.Category
                    cartsel.FeatureType = f.FeatureType
                    If Not cartItemsWithCategory.ContainsKey(f.ID) Then cartItemsWithCategory.Add(f.ID, cartsel)
                End If
                catalog.Refresh(sp, False, True, cartItemsWithCategory)
                RefreshFeatureList()
                'To update prices
                sCart.UpdateCartItemsPrice()

                ' when an item is added uoDo remove should be set to false and lcear stack
                ClearUnDoStack()

                SetSession(CatalogManagerKey, Me.ValuesForSetSession)

            Else
                Exit Sub
            End If


        End If
    End Sub

    ' clears all selected choices in a bundle \Service plan
    Private Sub UpdateSelectedChoices(ByVal itemID As String)
        Dim item As ICartItem

        For Each i As ICartItem In catalog.Cart.CartItems.Values
            If i.ID = itemID Then
                item = i
                Exit For
            Else
                If i.Children.ContainsKey(itemID) Then
                    item = DirectCast(i.Children(itemID), BLServicePlan)
                End If
            End If
        Next
        'DirectCast(catalog.Cart, ShoppingCart).ClearMessage()
        '' set cart notification message
        'DirectCast(catalog.Cart, ShoppingCart).SetMessageInput("Remove", item.Description)

        If item.Type = ItemType.Bundle Then
            For Each sp As BLServicePlan In item.Children.Values
                For Each f As BLFeature In sp.Features.Values
                    If f.FeatureType = FeatureType.IsOptional AndAlso Not f.ChoicesSelection Is Nothing Then
                        f.SelectedChoices.Clear()
                    End If
                Next
            Next
        Else
            For Each f As BLFeature In item.Children.Values
                If f.FeatureType = FeatureType.IsOptional AndAlso Not f.ChoicesSelection Is Nothing Then
                    f.SelectedChoices.Clear()
                End If
            Next
        End If

    End Sub

    Private Function UpdateSelectedChoices(ByVal objFeature As BLFeature, ByVal choiceID As String, ByVal Add As Boolean, ByRef cartitems As Dictionary(Of String, CartSelections), Optional ByVal sp As BLServicePlan = Nothing) As String
        Try
            If Add Then

                receivers = GenerateReceivers()

                If (Not receivers.ContainsKey(choiceID)) Then

                    If objFeature.ChoicesSelection.Count < objFeature.MaxChoiceSelection Then
                        objFeature.SelectedChoices.Add(choiceID)
                    Else
                        If objFeature.MaxChoiceSelection = 1 Then
                            objFeature.SelectedChoices.RemoveAt(0)
                            objFeature.SelectedChoices.Add(choiceID)
                        Else
                            _message.SetMessageResult(String.Empty, String.Empty, NotificationCode.CannotAddCustomization, NotificationSeverity.IsError)
                        End If
                    End If

                    If objFeature.ID = BLCommon.GetKey(BLCommon.Receivers.HDTV_TIER, receivers) Then
                        UpdateHDTV_DVR_Service(sp)
                    End If

                Else
                    Dim strTemp As String = BLCommon.GetKey(BLCommon.Receivers.TV_NUMBERS, receivers)
                    Dim subitem As ISubCartItem
                    If sp.Features.TryGetValue(strTemp, subitem) Then
                        Dim f As BLFeature = DirectCast(subitem, BLFeature)
                        Dim intCount As Integer = f.SelectedChoices.Count

                        Select Case receivers(choiceID)

                            Case BLCommon.Receivers.RECEIVER
                                Select Case intCount
                                    Case 0
                                        f.SelectedChoices.Add("1" & BLCommon.GetKey(BLCommon.Receivers.INCLUDED, receivers))
                                        UpdateSelectedChoices = BLCommon.GetKey(BLCommon.Receivers.INCLUDED, receivers)
                                    Case 4
                                        _message.SetMessageResult(String.Empty, String.Empty, NotificationCode.CannotAddCustomization, NotificationSeverity.IsError)
                                    Case Else
                                        f.SelectedChoices.Add(intCount + 1 & BLCommon.GetKey(BLCommon.Receivers.RECEIVER, receivers))
                                End Select
                                UpdateTVOptions(sp, receivers, f.SelectedChoices)

                            Case BLCommon.Receivers.HD

                                If f.SelectedChoices.Contains("1" & BLCommon.GetKey(BLCommon.Receivers.HD, receivers)) Or f.SelectedChoices.Contains("2" & BLCommon.GetKey(BLCommon.Receivers.HD, receivers)) Or f.SelectedChoices.Contains("3" & BLCommon.GetKey(BLCommon.Receivers.HD, receivers)) Then
                                    _message.SetMessageResult(String.Empty, String.Empty, NotificationCode.CannotAddCustomization, NotificationSeverity.IsError)
                                    Exit Function
                                End If

                                Select Case intCount
                                    Case 0, 1, 2
                                        f.SelectedChoices.Add(intCount + 1 & BLCommon.GetKey(BLCommon.Receivers.HD, receivers))
                                    Case 4
                                        _message.SetMessageResult(String.Empty, String.Empty, NotificationCode.CannotAddCustomization, NotificationSeverity.IsError)
                                    Case Else
                                        f.SelectedChoices.Insert(2, "3" & BLCommon.GetKey(BLCommon.Receivers.HD, receivers))
                                End Select
                                UpdateTVOptions(sp, receivers, f.SelectedChoices)


                            Case BLCommon.Receivers.DVR_1, BLCommon.Receivers.HD_1

                                If intCount > 0 Then
                                    If f.SelectedChoices(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.DVR_MULTI, receivers) Or f.SelectedChoices(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, receivers) Then
                                        f.SelectedChoices.RemoveAt(0)
                                        f.SelectedChoices.RemoveAt(0)
                                    Else
                                        If f.SelectedChoices(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.HD_1, receivers) Or f.SelectedChoices(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.DVR_1, receivers) Then
                                            f.SelectedChoices.RemoveAt(0)
                                        End If
                                    End If
                                End If
                                intCount = f.SelectedChoices.Count
                                Select Case intCount
                                    Case 0
                                        f.SelectedChoices.Add("1" & BLCommon.GetKey(receivers(choiceID), receivers))
                                    Case Else
                                        f.SelectedChoices.Insert(0, "1" & BLCommon.GetKey(receivers(choiceID), receivers))
                                End Select
                                UpdateTVOptions(sp, receivers, f.SelectedChoices)

                            Case BLCommon.Receivers.DVR_MULTI

                                If intCount > 0 Then
                                    If f.SelectedChoices.Contains("1" & BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, receivers)) Then
                                        f.SelectedChoices.RemoveAt(0)
                                        f.SelectedChoices.RemoveAt(0)
                                    Else
                                        f.SelectedChoices.RemoveAt(0)
                                    End If
                                End If
                                intCount = f.SelectedChoices.Count

                                If f.SelectedChoices.Contains("3" & BLCommon.GetKey(BLCommon.Receivers.HD, receivers)) Then
                                    f.SelectedChoices.RemoveAt(1)
                                    f.SelectedChoices.Insert(0, 1 & BLCommon.GetKey(BLCommon.Receivers.DVR_MULTI, receivers))
                                    f.SelectedChoices.Insert(1, 2 & BLCommon.GetKey(BLCommon.Receivers.EQUIP_2, receivers))
                                    f.SelectedChoices.Insert(2, 3 & BLCommon.GetKey(BLCommon.Receivers.HD, receivers))
                                Else
                                    f.SelectedChoices.Insert(0, 1 & BLCommon.GetKey(BLCommon.Receivers.DVR_MULTI, receivers))
                                    f.SelectedChoices.Insert(1, 2 & BLCommon.GetKey(BLCommon.Receivers.EQUIP_2, receivers))
                                End If
                                UpdateSelectedChoices = BLCommon.GetKey(BLCommon.Receivers.EQUIP_2, receivers)
                                UpdateTVOptions(sp, receivers, f.SelectedChoices)

                            Case BLCommon.Receivers.HD_MULTI

                                If intCount > 0 Then
                                    If f.SelectedChoices(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.DVR_MULTI, receivers) Then
                                        f.SelectedChoices.RemoveAt(0)
                                        f.SelectedChoices.RemoveAt(0)
                                    Else
                                        f.SelectedChoices.RemoveAt(0)
                                    End If
                                End If

                                intCount = f.SelectedChoices.Count
                                Select Case intCount
                                    Case 0, 1, 2
                                        f.SelectedChoices.Insert(0, 1 & BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, receivers))
                                        f.SelectedChoices.Insert(1, 2 & BLCommon.GetKey(BLCommon.Receivers.HD_EQUIP_2, receivers))
                                    Case Else
                                        If f.SelectedChoices.Contains("3" & BLCommon.GetKey(BLCommon.Receivers.HD_1, receivers)) Then
                                            f.SelectedChoices.RemoveAt(1)
                                            f.SelectedChoices.Insert(0, 1 & BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, receivers))
                                            f.SelectedChoices.Insert(1, 2 & BLCommon.GetKey(BLCommon.Receivers.HD_EQUIP_2, receivers))
                                            f.SelectedChoices.Insert(2, 3 & BLCommon.GetKey(BLCommon.Receivers.HD_1, receivers))
                                        Else
                                            f.SelectedChoices.Insert(0, 1 & BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, receivers))
                                            f.SelectedChoices.Insert(1, 2 & BLCommon.GetKey(BLCommon.Receivers.HD_EQUIP_2, receivers))
                                        End If
                                End Select
                                UpdateSelectedChoices = BLCommon.GetKey(BLCommon.Receivers.HD_EQUIP_2, receivers)
                                UpdateTVOptions(sp, receivers, f.SelectedChoices)

                            Case BLCommon.Receivers.EQUIP_2, BLCommon.Receivers.HD_EQUIP_2
                            Case BLCommon.Receivers.INCLUDED
                                Select Case intCount
                                    Case 0
                                        f.SelectedChoices.Add("1" & BLCommon.GetKey(BLCommon.Receivers.INCLUDED, receivers))
                                        UpdateSelectedChoices = BLCommon.GetKey(BLCommon.Receivers.INCLUDED, receivers)
                                    Case 4
                                        _message.SetMessageResult(String.Empty, String.Empty, NotificationCode.CannotAddCustomization, NotificationSeverity.IsError)
                                    Case Else
                                        f.SelectedChoices.Add(intCount + 1 & BLCommon.GetKey(BLCommon.Receivers.RECEIVER, receivers))
                                End Select
                                UpdateTVOptions(sp, receivers, f.SelectedChoices)
                            Case Else
                                If objFeature.ChoicesSelection.Count < objFeature.MaxChoiceSelection Then
                                    objFeature.SelectedChoices.Add(choiceID)
                                Else
                                    If objFeature.MaxChoiceSelection = 1 Then
                                        objFeature.SelectedChoices.RemoveAt(0)
                                        objFeature.SelectedChoices.Add(choiceID)
                                    Else
                                        _message.SetMessageResult(String.Empty, String.Empty, NotificationCode.CannotAddCustomization, NotificationSeverity.IsError)
                                    End If
                                End If
                        End Select
                        If f.SelectedChoices.Count > 0 Then
                            Dim cartsel As CartSelections
                            cartsel.Category = f.Category
                            cartsel.FeatureType = f.FeatureType
                            If Not cartitems.ContainsKey(f.ID) Then cartitems.Add(f.ID, cartsel)
                        End If
                    End If
                    UpdateHDTV_DVR_Service(sp)
                End If

            Else

                receivers = GenerateReceivers()
                If receivers.ContainsKey(choiceID) Then

                    If receivers(choiceID) = BLCommon.Receivers.HDTV_SERVICE Or receivers(choiceID) = BLCommon.Receivers.DVR_SERVICE Then
                        If objFeature.ChoicesSelection.Contains(choiceID) Then objFeature.SelectedChoices.Remove(choiceID)
                        UpdateHDTV_DVR_Service(sp)
                        Exit Try
                    End If

                    Dim subitem As ISubCartItem
                    Dim f As BLFeature

                    If sp.Features.TryGetValue(BLCommon.GetKey(BLCommon.Receivers.TV_NUMBERS, receivers), subitem) Then
                        f = DirectCast(subitem, BLFeature)
                    Else
                        Exit Try
                    End If
                    'UPDATE TV NUMBER Option1

                    If f.SelectedChoices.Contains("1" & choiceID) Then
                        If choiceID = BLCommon.GetKey(BLCommon.Receivers.DVR_MULTI, receivers) Or choiceID = BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, receivers) Then
                            f.SelectedChoices.RemoveAt(0)
                            f.SelectedChoices.RemoveAt(0)
                            UpdateSelectedChoices = UpdateTVOptions(sp, receivers, f.SelectedChoices)
                            UpdateHDTV_DVR_Service(sp)
                            If f.SelectedChoices.Count > 0 Then
                                Dim cartsel As CartSelections
                                cartsel.Category = f.Category
                                cartsel.FeatureType = f.FeatureType
                                If Not cartitems.ContainsKey(f.ID) Then cartitems.Add(f.ID, cartsel)
                            End If
                            Exit Try
                        Else
                            f.SelectedChoices.RemoveAt(0)
                            UpdateSelectedChoices = UpdateTVOptions(sp, receivers, f.SelectedChoices)
                            UpdateHDTV_DVR_Service(sp)
                            If f.SelectedChoices.Count > 0 Then
                                Dim cartsel As CartSelections
                                cartsel.Category = f.Category
                                cartsel.FeatureType = f.FeatureType
                                If Not cartitems.ContainsKey(f.ID) Then cartitems.Add(f.ID, cartsel)
                            End If
                            Exit Try
                        End If
                    End If

                    'UPDATE TV NUMBER Option2
                    If f.SelectedChoices.Contains("2" & choiceID) Then
                        f.SelectedChoices.RemoveAt(1)
                        UpdateTVOptions(sp, receivers, f.SelectedChoices)
                        UpdateHDTV_DVR_Service(sp)
                        If f.SelectedChoices.Count > 0 Then
                            Dim cartsel As CartSelections
                            cartsel.Category = f.Category
                            cartsel.FeatureType = f.FeatureType
                            If Not cartitems.ContainsKey(f.ID) Then cartitems.Add(f.ID, cartsel)
                        End If
                        Exit Try
                    End If


                    'UPDATE TV NUMBER Option3
                    If f.SelectedChoices.Contains("3" & choiceID) Then
                        f.SelectedChoices.RemoveAt(2)
                        UpdateTVOptions(sp, receivers, f.SelectedChoices)
                        UpdateHDTV_DVR_Service(sp)
                        If f.SelectedChoices.Count > 0 Then
                            Dim cartsel As CartSelections
                            cartsel.Category = f.Category
                            cartsel.FeatureType = f.FeatureType
                            If Not cartitems.ContainsKey(f.ID) Then cartitems.Add(f.ID, cartsel)
                        End If
                        Exit Try
                    End If

                    'UPDATE TV NUMBER Option4
                    If f.SelectedChoices.Contains("4" & choiceID) Then
                        f.SelectedChoices.RemoveAt(3)
                        UpdateTVOptions(sp, receivers, f.SelectedChoices)
                        UpdateHDTV_DVR_Service(sp)
                        If f.SelectedChoices.Count > 0 Then
                            Dim cartsel As CartSelections
                            cartsel.Category = f.Category
                            cartsel.FeatureType = f.FeatureType
                            If Not cartitems.ContainsKey(f.ID) Then cartitems.Add(f.ID, cartsel)
                        End If
                        Exit Try
                    End If
                Else
                    If objFeature.ChoicesSelection.Contains(choiceID) Then objFeature.SelectedChoices.Remove(choiceID)
                    If objFeature.ID = BLCommon.GetKey(BLCommon.Receivers.HDTV_TIER, receivers) Then
                        UpdateHDTV_DVR_Service(sp)
                    End If
                End If

            End If
        Catch ex As Exception
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        End Try
    End Function

    Private Function UpdateHDTV_DVR_Service(ByRef sp As BLServicePlan) As Boolean
        Try
            Dim strTempKey_HDTVDVR As String = BLCommon.GetKey(BLCommon.Receivers.HDTV_OR_DVR_SERVICE, receivers)
            Dim strTempKey_TVNUM As String = BLCommon.GetKey(BLCommon.Receivers.TV_NUMBERS, receivers)
            Dim strTempKey_HDTVTIER As String = BLCommon.GetKey(BLCommon.Receivers.HDTV_TIER, receivers)

            Dim subItem_HDTVDVR As ISubCartItem
            Dim subitem_TVNUM As ISubCartItem
            Dim subitem_HDTVTIER As ISubCartItem

            If sp.Features.TryGetValue(strTempKey_HDTVDVR, subItem_HDTVDVR) Then
                Dim f_HDTVDVR As BLFeature = CType(subItem_HDTVDVR, BLFeature)
                'f_HDTVDVR.SelectedChoices.Clear()

                If sp.Features.TryGetValue(strTempKey_HDTVTIER, subitem_HDTVTIER) Then
                    Dim f_HDTVTier As BLFeature = CType(subitem_HDTVTIER, BLFeature)
                    If f_HDTVTier.SelectedChoices.Count > 0 Then
                        If Not f_HDTVDVR.SelectedChoices.Contains(BLCommon.GetKey(BLCommon.Receivers.HDTV_SERVICE, receivers)) Then f_HDTVDVR.SelectedChoices.Add(BLCommon.GetKey(BLCommon.Receivers.HDTV_SERVICE, receivers))
                    End If
                End If

                If sp.Features.TryGetValue(strTempKey_TVNUM, subitem_TVNUM) Then
                    Dim f_TVNUM As BLFeature = CType(subitem_TVNUM, BLFeature)
                    If f_TVNUM.SelectedChoices.Count > 0 Then

                        If f_TVNUM.SelectedChoices.Exists(AddressOf IsHDTV) Then
                            If Not f_HDTVDVR.SelectedChoices.Contains(BLCommon.GetKey(BLCommon.Receivers.HDTV_SERVICE, receivers)) Then f_HDTVDVR.SelectedChoices.Add(BLCommon.GetKey(BLCommon.Receivers.HDTV_SERVICE, receivers))
                        End If

                        If f_TVNUM.SelectedChoices.Exists(AddressOf IsDVR) Then
                            If Not f_HDTVDVR.SelectedChoices.Contains(BLCommon.GetKey(BLCommon.Receivers.DVR_SERVICE, receivers)) Then f_HDTVDVR.SelectedChoices.Add(BLCommon.GetKey(BLCommon.Receivers.DVR_SERVICE, receivers))
                        End If
                    End If
                End If

            End If

        Catch ex As Exception
            Throw ex
        End Try

    End Function

    Private Function IsHDTV(ByVal s As String) As Boolean
        Try
            If InStr(s, BLCommon.GetKey(BLCommon.Receivers.HD, receivers)) > 0 Or InStr(s, BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, receivers)) > 0 Then
                Return True
            Else
                Return False
            End If

        Catch ex As Exception
            Return False
        End Try
    End Function

    Private Function IsDVR(ByVal s As String) As Boolean
        Try
            If InStr(s, BLCommon.GetKey(BLCommon.Receivers.DVR_1, receivers)) > 0 Or InStr(s, BLCommon.GetKey(BLCommon.Receivers.DVR_MULTI, receivers)) > 0 Or InStr(s, BLCommon.GetKey(BLCommon.Receivers.HD_1, receivers)) > 0 Then
                Return True
            Else
                Return False
            End If

        Catch ex As Exception
            Return False
        End Try
    End Function

    Private Function GenerateReceivers() As Dictionary(Of String, BLCommon.Receivers)
        Try
            If Not HttpContext.Current.Application("Receivers") Is Nothing Then
                Return CType(HttpContext.Current.Application("Receivers"), Dictionary(Of String, BLCommon.Receivers))
            Else
                Return Nothing
            End If
        Catch ex As Exception
            Throw ex
        End Try
    End Function

    Private Function UpdateTVOptions(ByRef sp As BLServicePlan, ByVal dict As Dictionary(Of String, Receivers), ByRef selections As List(Of String), Optional ByVal ParentID As String = Nothing, Optional ByVal choiceID As String = Nothing) As String
        Try
            Dim subitem As ISubCartItem
            Dim f As BLFeature

            Dim objList As New List(Of String)

            If Not ParentID Is Nothing Then
                Select Case dict(ParentID)
                    Case BLCommon.Receivers.TV_1
                        If selections.Count = 0 Then
                            selections.Add("1" & choiceID)
                        Else
                            If selections.Count > 1 AndAlso (selections(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.DVR_MULTI, dict) Or selections(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, dict)) Then
                                selections(0) = "1" & choiceID
                                selections.RemoveAt(1)
                            Else
                                selections(0) = "1" & choiceID
                            End If
                        End If
                    Case BLCommon.Receivers.TV_2
                        If selections.Count > 1 AndAlso (selections(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.DVR_MULTI, dict) Or selections(0) = "1" & BLCommon.GetKey(BLCommon.Receivers.HD_MULTI, dict)) Then
                            _message.SetMessageResult(String.Empty, String.Empty, NotificationCode.CannotAddCustomization, NotificationSeverity.IsError)
                            Return Nothing
                        End If
                        If selections.Count = 1 Then
                            selections.Add("2" & choiceID)
                        Else
                            selections(1) = "2" & choiceID
                        End If
                    Case BLCommon.Receivers.TV_3
                        If selections.Count = 2 Then
                            selections.Add("3" & choiceID)
                        Else
                            selections(2) = "3" & choiceID
                        End If
                    Case BLCommon.Receivers.TV_4
                        If selections.Count = 3 Then
                            selections.Add("4" & choiceID)
                        Else
                            selections(3) = "4" & choiceID
                        End If
                End Select
            End If
            'UPDATE TV 1 Option
            If sp.Features.TryGetValue(BLCommon.GetKey(BLCommon.Receivers.TV_1, dict), subitem) Then
                f = DirectCast(subitem, BLFeature)
                f.SelectedChoices.Clear()
                If selections.Count > 0 Then
                    Dim strTemp As String = Right(selections(0), selections(0).Length - 1)
                    If strTemp = BLCommon.GetKey(BLCommon.Receivers.RECEIVER, dict) Then
                        Dim strTemp1 As String = BLCommon.GetKey(BLCommon.Receivers.INCLUDED, dict)
                        f.SelectedChoices.Add(strTemp1)
                        objList.Add("1" & strTemp1)
                        UpdateTVOptions = strTemp1
                    Else
                        f.SelectedChoices.Add(Right(selections(0), selections(0).Length - 1))
                        objList.Add("1" & Right(selections(0), selections(0).Length - 1))
                    End If
                End If
            End If

            'UPDATE TV 2 Option
            If sp.Features.TryGetValue(BLCommon.GetKey(BLCommon.Receivers.TV_2, dict), subitem) Then
                f = DirectCast(subitem, BLFeature)
                f.SelectedChoices.Clear()
                If selections.Count > 1 Then
                    Dim strTemp As String = Right(selections(1), selections(1).Length - 1)
                    If strTemp = BLCommon.GetKey(BLCommon.Receivers.HD_EQUIP_2, dict) Or strTemp = BLCommon.GetKey(BLCommon.Receivers.EQUIP_2, dict) Then
                        Dim subItem1 As ISubCartItem
                        If f.Choices.TryGetValue(strTemp, subItem1) Then
                            Dim f1 As BLFeature = DirectCast(subItem1, BLFeature)
                            f1.ISRemovable = False
                        End If
                    End If
                    If strTemp = BLCommon.GetKey(BLCommon.Receivers.INCLUDED, dict) Then
                        Dim strTemp1 As String = BLCommon.GetKey(BLCommon.Receivers.RECEIVER, dict)
                        f.SelectedChoices.Add(strTemp1)
                        objList.Add("2" & strTemp1)
                        UpdateTVOptions = strTemp1
                    Else
                        f.SelectedChoices.Add(strTemp)
                        objList.Add("2" & strTemp)
                    End If

                End If
            End If

            'UPDATE TV 3 Option
            If sp.Features.TryGetValue(BLCommon.GetKey(BLCommon.Receivers.TV_3, dict), subitem) Then
                f = DirectCast(subitem, BLFeature)
                f.SelectedChoices.Clear()
                If selections.Count > 2 Then
                    f.SelectedChoices.Add(Right(selections(2), selections(2).Length - 1))
                    'selections.Add("3" & Right(selections(2), selections(2).Length - 1))
                    'selections.RemoveAt(0)
                    objList.Add("3" & Right(selections(2), selections(2).Length - 1))
                End If
            End If

            'UPDATE TV 4 Option
            If sp.Features.TryGetValue(BLCommon.GetKey(BLCommon.Receivers.TV_4, dict), subitem) Then
                f = DirectCast(subitem, BLFeature)
                f.SelectedChoices.Clear()
                If selections.Count > 3 Then
                    f.SelectedChoices.Add(Right(selections(3), selections(3).Length - 1))
                    'selections.Add("4" & Right(selections(3), selections(3).Length - 1))
                    'selections.RemoveAt(0)
                    objList.Add("4" & Right(selections(3), selections(3).Length - 1))
                End If
            End If

            If sp.Features.TryGetValue(BLCommon.GetKey(BLCommon.Receivers.TV_NUMBERS, dict), subitem) Then
                f = DirectCast(subitem, BLFeature)
                f.SelectedChoices.Clear()
                f.SelectedChoices.AddRange(objList)
                If ParentID Is Nothing Then
                    f.QuantitySelected = objList.Count
                End If
                If objList.Count > 0 Then
                    f.ISSelected = True
                End If
            End If

        Catch ex As Exception
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        End Try
    End Function

    Private Sub UpdateSelectedChoices(ByVal oldSP As BLServicePlan, ByVal newSP As ICartItem)
        Dim objFeature As BLFeature
        For Each f As BLFeature In newSP.Children.Values
            If oldSP.Features.ContainsKey(f.ID) Then
                objFeature = CType(oldSP.Features(f.ID), BLFeature)
                If (Not objFeature.ChoicesSelection Is Nothing AndAlso objFeature.ChoicesSelection.Count > 0) Then
                    Dim arrSel() As String
                    arrSel = objFeature.ChoicesSelection.ToArray()
                    f.ChoicesSelection.AddRange(arrSel)
                    objFeature.SelectedChoices.Clear()
                    f.QuantitySelected = CType(oldSP.Features(f.ID), BLFeature).QuantitySelected
                    objFeature.QuantitySelected = 0
                End If
            End If
        Next
    End Sub

    Private Function FindOption(ByVal spID As String, ByVal itemID As String) As BLFeature

        Dim sp As BLServicePlan

        If catalog.Cart Is Nothing Then
            Return Nothing
        End If

        If catalog.Cart.CartItems.ContainsKey(spID) Then
            sp = CType(catalog.Cart.CartItems(spID), BLServicePlan)
        Else
            For Each objCartItem As ICartItem In catalog.Cart.CartItems.Values
                If objCartItem.Type = ItemType.Bundle AndAlso objCartItem.Children.ContainsKey(spID) Then
                    sp = CType(objCartItem.Children(spID), BLServicePlan)
                End If
            Next
        End If

        If sp Is Nothing Then
            sp = CType(catalog.ServicePlans(spID), BLServicePlan)
        End If

        For Each f As BLFeature In sp.Features.Values
            If f.ID = itemID Then
                Return Nothing
            Else
                If Not f.Choices Is Nothing AndAlso f.Choices.Count > 0 Then
                    Dim objChoice As ISubCartItem
                    If f.Choices.TryGetValue(itemID, objChoice) Then
                        Return f
                    End If
                End If
            End If
        Next
    End Function

    ''' <summary>
    ''' this method provides functionality to remove Bundle / Service Plan / Promotion from the shopping cart.
    ''' </summary>
    ''' <param name="itemID">ID of BUndle/ Service Plan that should be removed from cart</param>
    ''' <remarks>
    ''' From given ItemID finds the item, and calls RemoveItemFromCart.
    ''' Dynamic Bundling will be done.
    ''' Updates UndoStack with the new item.
    ''' Refreshes FeatureList.
    ''' Invokes Notify delegate about any unexpected changes to ShoppingCart.
    ''' Updates Shopping cart price.
    ''' After all the Chages are done adds CatalogManager to session.
    ''' </remarks>
    Public Overrides Function RemoveCartItem(ByVal trackID As String, ByVal itemID As String) As INotification
        Try
            PopulateLocalVariables(trackID)
            Dim strName As String
            ' set cart notification message
            If catalog.Cart.CartItems.ContainsKey(itemID) Then
                strName = catalog.Cart.CartItems(itemID).Name
                ' when an item is removed push it to undo remove stack
                PushToUnDoStack(CreateUnDoStackItem(catalog.Cart.CartItems(itemID)))
            Else
                For Each i As ICartItem In catalog.Cart.CartItems.Values
                    If i.Type = ItemType.Bundle Then
                        For Each si As BLServicePlan In i.Children.Values
                            If si.ID = itemID Then
                                strName = si.Name
                                ' when an item is removed puch it to undo remove stack
                                PushToUnDoStack(CreateUnDoStackItem(si))
                                Exit For
                            End If
                        Next
                    End If
                Next
            End If

            _message = New Notification(NotificationAction.Remove, strName, NotificationCode.Success)

            RemoveItemFromCart(itemID, Nothing)

            RefreshFeatureList()
            'To update prices
            sCart.UpdateCartItemsPrice()

            SetSession(CatalogManagerKey, Me.ValuesForSetSession)

            Return _message
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot remove from cart", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try

        Return Nothing
    End Function

    Private Sub RemoveItemFromCart(ByVal itemID As String, ByVal userSelections As Dictionary(Of String, CartSelections))
        Dim item As ICartItem
        Dim subItem As ISubCartItem
        If catalog.Cart.CartItems.ContainsKey(itemID) Then
            item = catalog.Cart.CartItems(itemID)
        Else
            For Each i As ICartItem In catalog.Cart.CartItems.Values
                If i.Type = ItemType.Bundle Then
                    If i.Children.ContainsKey(itemID) Then
                        subItem = i.Children(itemID)
                    End If
                End If
            Next
        End If
        ''If userSelections Is Nothing Then userSelections = GetCartItemsWithcategory()

        If userSelections Is Nothing Then
            userSelections = GetCartItemsWithcategory()
            UpdateSelectedChoices(itemID)
        End If

        userSelections.Remove(itemID)
        If Not item Is Nothing Then
            sCart.RemoveCartItem(item.ID)
            catalog.Refresh(item, True, False, userSelections)
            'RefreshFeatureList(item)
            'RefreshCustomizationList(item)


        Else
            If Not subItem Is Nothing Then
                RemoveBundle(userSelections, True)
                catalog.Refresh(catalog.ServicePlans(subItem.ID), True, False, userSelections)
                'RefreshFeatureList(catalog.ServicePlans(subItem.ID))
                'RefreshCustomizationList(catalog.ServicePlans(subItem.ID))

            End If
        End If

    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="itemID">ID of feature that should be removed from cart</param>
    ''' <remarks>
    ''' From given ItemID finds the feature.
    ''' Dynamic Bundling will be done.
    ''' Updates UndoStack with the new item, and removes that feature from UserSelectedList.
    ''' Finds service plan with the new UserSelectionList, by calling FindServiceplan.
    ''' Adds the ServicePlan found in above method to cart. 
    ''' If there is a change in Service plan with current selections Carries any customization selections to new ServicePlan.
    ''' Refreshes Catalog,FeatureList.
    ''' Invokes Notify delegate about any unexpected changes to ShoppingCart.
    ''' Updates Shopping cart price.
    ''' After all the Chages are done adds CatalogManager to session.
    ''' </remarks>
    Public Overrides Function RemoveSubCartItem(ByVal trackID As String, ByVal itemID As String, ByVal parentid As String) As INotification
        Try
            PopulateLocalVariables(trackID)
            If featureList.ContainsKey(itemID) Then
                Dim f As BLFeature = DirectCast(featureList(itemID), BLFeature)
                Dim objCartSelection As CartSelections
                Dim cartItemsWithCategory As Dictionary(Of String, CartSelections) = GetCartItemsWithcategory()
                If cartItemsWithCategory.ContainsKey(itemID) Then
                    objCartSelection = cartItemsWithCategory(itemID)
                    cartItemsWithCategory.Remove(itemID)
                End If

                ' set cart notification message
                _message = New Notification(NotificationAction.Remove, f.Name, NotificationCode.Success)

                If parentid Is Nothing Then

                    ' this remove is not from options page, so bundling should be dine

                    Dim spID As String = FindServicePlanInCartByCategory(f.Category)
                    Dim objFeature As BLFeature = FindOption(spID, itemID)

                    Dim sp As BLServicePlan = FindServicePlan(f.Category, cartItemsWithCategory)

                    If Not objFeature Is Nothing Then
                        Dim strTemp As String = UpdateSelectedChoices(objFeature, itemID, False, cartItemsWithCategory, sp)
                        If Not strTemp Is Nothing Then
                            cartItemsWithCategory.Add(strTemp, objCartSelection)
                        End If
                    End If

                    If Not DirectCast(catalog.Cart, BLShoppingCart).ContainsThisKey(sp.ID) Then
                        ' this service plan is not in cart, new service plan
                        ' set cart notification message
                        _message.SetMessageResult(String.Empty, sp.Name, NotificationCode.NewServicePlan, NotificationSeverity.IsMessage)

                    End If

                    AddItemToCart(sp, cartItemsWithCategory)


                    'To update prices
                    sCart.UpdateCartItemsPrice()
                Else
                    ' this remove is from select options page, don't need to do bundling
                    Dim parent As ISubCartItem = CType(catalog.Cart, BLShoppingCart).GetParentFeature(itemID, parentid)

                    If Not parent Is Nothing Then
                        Dim parentFeature As BLFeature = CType(parent, BLFeature)
                        If parentFeature.ChoicesSelection.Contains(itemID) Then parentFeature.SelectedChoices.Remove(itemID)
                        receivers = GenerateReceivers()
                        If receivers IsNot Nothing AndAlso receivers.ContainsKey(parentFeature.ID) Then

                            Dim sp As BLServicePlan
                            Dim subitem As ISubCartItem
                            For Each objitem As ICartItem In catalog.Cart.CartItems.Values
                                If objitem.Type = ItemType.Bundle Then
                                    For Each objsubitem As ISubCartItem In objitem.Children.Values
                                        If objsubitem.Category = parentFeature.Category Then
                                            sp = CType(objsubitem, BLServicePlan)
                                            Exit For
                                        End If
                                    Next
                                Else
                                    If objitem.Category = parentFeature.Category Then
                                        sp = CType(objitem, BLServicePlan)
                                        Exit For
                                    End If
                                End If
                            Next

                            If sp.Features.TryGetValue(BLCommon.GetKey(BLCommon.Receivers.TV_NUMBERS, receivers), subitem) Then
                                f = DirectCast(subitem, BLFeature)
                                Select Case receivers(parentFeature.ID)
                                    Case BLCommon.Receivers.TV_1
                                        If f.SelectedChoices.Count > 0 Then
                                            f.SelectedChoices.RemoveAt(0)
                                            If parentid Is Nothing Then
                                                f.QuantitySelected = f.QuantitySelected - 1
                                            End If
                                        End If
                                    Case BLCommon.Receivers.TV_2
                                        If f.SelectedChoices.Count > 1 Then
                                            f.SelectedChoices.RemoveAt(1)
                                            If parentid Is Nothing Then
                                                f.QuantitySelected = f.QuantitySelected - 1
                                            End If
                                        End If
                                    Case BLCommon.Receivers.TV_3
                                        If f.SelectedChoices.Count > 2 Then
                                            f.SelectedChoices.RemoveAt(2)
                                            If parentid Is Nothing Then
                                                f.QuantitySelected = f.QuantitySelected - 1
                                            End If
                                        End If
                                    Case BLCommon.Receivers.TV_4
                                        If f.SelectedChoices.Count > 3 Then
                                            f.SelectedChoices.RemoveAt(3)
                                            If parentid Is Nothing Then
                                                f.QuantitySelected = f.QuantitySelected - 1
                                            End If
                                        End If
                                End Select
                            End If

                        End If
                        catalog.RefreshFeature(parentFeature, False, True, cartItemsWithCategory)
                    End If
                End If

                RefreshFeatureList()
                ' when an itemis removed add it to unDoRemoveStack
                PushToUnDoStack(CreateUnDoStackItem(DirectCast(featureList(itemID), BLFeature)))

                SetSession(CatalogManagerKey, Me.ValuesForSetSession)

                Return _message
            End If
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot remove feature from cart", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try

        Return Nothing

    End Function

    Private Sub PopulateCartIfPersisted(ByVal am As BLAccountManager)
        Try
            'check if returning user and pre-populate the cart with persisted data
            'TO DO: if cookie present then add this 
            'If AccountManager.Instance.account.IsReturningUser Then
            'retrieve persisted cart items information from the corresponding provider
            Dim objPersistedCart As ShoppingCart = am.gwyShoppingCart 'GetCartItemsFromDB()
            If Not objPersistedCart Is Nothing Then
                For Each obj As Items In objPersistedCart.Offers.Values
                    'Loop through the Serviceplans and add them to the cart
                    If obj.Type = GwyItemType.ServicePlan Then
                        If catalog.ServicePlans.ContainsKey(ItemType.ServicePlan & obj.ID) Then
                            AddItemToCart(catalog.ServicePlans(ItemType.ServicePlan & obj.ID))
                            'Loop through the customizations and choices and add them to the cart
                            If Not obj.SubItems Is Nothing Then
                                For Each objcust As Items In obj.SubItems.Values
                                    If Not objcust.SubItems Is Nothing Then
                                        For Each objchoices As Items In objcust.SubItems.Values
                                            If objchoices.Number <> 0 Then
                                                Dim item As ISubCartItem
                                                If featureList.TryGetValue(ItemType.Feature & objchoices.ID, item) Then
                                                    AddSubcartItem(Nothing, ItemType.Feature & objchoices.ID, objchoices.Number)
                                                End If
                                                'AddAnOption(ItemType.Feature & objchoices.ID, objchoices.Number)
                                            Else
                                                Dim item As ISubCartItem
                                                If featureList.TryGetValue(ItemType.Feature & objchoices.ID, item) Then
                                                    AddSubItemToCart_Checkout(item)
                                                End If
                                                'AddAnOption(ItemType.Feature & objchoices.ID)
                                            End If
                                        Next
                                    Else
                                        If objcust.Number <> 0 Then
                                            Dim item As ISubCartItem
                                            If featureList.TryGetValue(ItemType.Feature & objcust.ID, item) Then
                                                AddSubcartItem(Nothing, ItemType.Feature & objcust.ID, objcust.Number)
                                            End If
                                        End If
                                    End If
                                Next
                            End If
                        End If
                    Else
                        'If bundle then add to the cart and exit this routine as there can be only one bundle in a cart
                        If catalog.Bundles.ContainsKey(ItemType.Bundle & obj.ID) Then
                            AddItemToCart(catalog.Bundles(ItemType.Bundle & obj.ID))
                            If Not obj.SubItems Is Nothing Then
                                For Each objsp As Items In obj.SubItems.Values
                                    If Not objsp.SubItems Is Nothing Then
                                        'Loop through the customizations and choices and add them to the cart
                                        For Each objcust As Items In objsp.SubItems.Values
                                            If Not objcust.SubItems Is Nothing Then
                                                For Each objchoices As Items In objcust.SubItems.Values
                                                    Dim item As ISubCartItem
                                                    If featureList.TryGetValue(ItemType.Feature & objchoices.ID, item) Then
                                                        AddSubItemToCart_Checkout(item)
                                                    End If
                                                    'AddAnOption(ItemType.Feature & objchoices.ID)
                                                Next
                                            End If
                                        Next
                                    End If
                                Next
                            End If
                        End If
                        Exit For
                    End If
                Next
            End If
            'End If
            RefreshFeatureList()
            ' after shopping cart is populated clear acount manager's gate way shopping cart property
            am.gwyShoppingCart = Nothing
        Catch ex As Exception
            BLCommon.LogException(New ApplicationException("Cannot build cart from persisted items", ex), ExceptionSeverity.Catastrophic)
            'throw ex
        End Try
    End Sub


    ''' <summary>
    ''' Stores Shopping Cart Information in Charter.com database, with cookie id.
    ''' </summary>
    ''' <remarks> </remarks>
    Public Overrides Sub PersistShoppingcart(ByVal trackid As String)
        Try
            PopulateLocalVariables(trackid)
            'Dim iProvider As IContentProvider = providerFactory.CreateProvider(Of IContentProvider)(BLCommon.AssemblyName)
            Dim iProvider As IContentProvider = CType(Activator.GetObject(GetType(IContentProvider), CStr(HttpContext.Current.Application("RemoteURL_ContentProvider"))), IContentProvider)
            Dim providerRequest As New EntityContent.PersistCartRequest
            Dim am As New BLAccountManager(CType(Session(BLCommon.AccountManagerKey), Dictionary(Of String, Object)))
            providerRequest.aAddress = ConvertBLAddressToGwyAddress(DirectCast(am.account.Address, BLAddress))
            providerRequest.GUID = am.CookieID
            providerRequest.sShoppingCart = PopulateGWYShoppingCart(catalog.Cart)
            iProvider.PersistCart(providerRequest)
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot build cart from persisted items", ex)
            BLCommon.LogException(aex, ExceptionSeverity.High)
            ' Throw aex
        End Try
    End Sub

    ''' <summary>
    ''' Undo a Previous Remove.
    ''' </summary>
    ''' <remarks>
    ''' Adds the last added item from stack to Shopping Cart by using AddCartItem.
    ''' Updates UnDoRemove Flag based on Stack count.
    ''' </remarks>
    ''' 
    Public Overrides Function UndoRemove(ByVal trackID As String) As INotification
        Try
            PopulateLocalVariables(trackID)
            If Not UndoStack Is Nothing Then
                If UndoStack.Count > 0 Then

                    Dim item As Items = UndoStack.Pop()

                    _undoremove = True

                    If UndoStack.Count > 0 Then
                        sCart.m_undo = True
                    Else
                        sCart.m_undo = False
                    End If

                    Dim userSelections As Dictionary(Of String, CartSelections)
                    Dim selection As CartSelections
                    _message = New Notification(NotificationAction.Add, item.Description, NotificationCode.Success)

                    Select Case item.Type
                        Case GwyItemType.Bundle
                            If catalog.Bundles.ContainsKey(item.ID) Then
                                AddItemToCart(catalog.Bundles(item.ID))
                                userSelections = GetCartItemsWithcategory()
                                Dim cz As BLFeature
                                ' For Each subItem As Items In item.SubItems.Values
                                For Each choice As Items In item.SubItems.Values
                                    selection.Category = featureList(choice.ID).Category
                                    selection.FeatureType = FeatureType.IsPlaceholder
                                    userSelections.Add(choice.ID, selection)
                                    cz = DirectCast(catalog.Cart, BLShoppingCart).FindPlaceholder(choice.ID)
                                    cz.ChoicesSelection.Add(choice.ID)
                                    catalog.RefreshFeature(cz, False, True, userSelections)
                                Next
                                'Next
                            End If
                        Case GwyItemType.ServicePlan
                            If catalog.ServicePlans.ContainsKey(item.ID) Then
                                AddItemToCart(catalog.ServicePlans(item.ID))
                                Dim cz As BLFeature
                                userSelections = GetCartItemsWithcategory()
                                For Each choice As Items In item.SubItems.Values
                                    selection.Category = featureList(choice.ID).Category
                                    selection.FeatureType = FeatureType.IsPlaceholder
                                    userSelections.Add(choice.ID, selection)
                                    cz = DirectCast(catalog.Cart, BLShoppingCart).FindPlaceholder(choice.ID)
                                    cz.ChoicesSelection.Add(choice.ID)
                                    catalog.RefreshFeature(cz, False, True, userSelections)
                                Next
                            End If
                        Case GwyItemType.Choice
                            'selection.Category = featureList(item.ID).Category
                            'selection.FeatureType = FeatureType.IsPlaceholder
                            'userSelections.Add(item.ID, selection)
                            AddSubItemToCart(featureList(item.ID))
                        Case Else
                            Throw New ApplicationException("This type is not Acceptable")
                    End Select

                    _undoremove = False
                    SetSession(CatalogManagerKey, Me.ValuesForSetSession)
                End If
            End If

            Return _message
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot un-do previous removal", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try
        Return Nothing
    End Function

    Private Sub AddToFeatureList(ByVal item As ISubCartItem)
        Dim category As FeatureCategory = DirectCast(item, BLFeature).FeatureCategory
        If item.Children Is Nothing OrElse item.Children.Count = 0 Then
            If Not featureList.ContainsKey(item.ID) Then
                ' If Not (category = FeatureCategory.Installation OrElse category = FeatureCategory.DataEquipment OrElse category = FeatureCategory.VideoEquipment OrElse category = FeatureCategory.VideoEquipment) Then
                featureList.Add(item.ID, item)
                'End If
            End If
        End If
    End Sub

    'Form a custom Feature List of IDs and deciding attributes associated with every Serviceplan 
    ' to help form a Service plan based on Features in the cart
    Private Sub AddToServiceFeatures(ByVal feature As ISubCartItem, ByVal serviceID As String)
        Try
            'Instantiate if not available
            If serviceFeatureList Is Nothing Then
                serviceFeatureList = New Dictionary(Of String, ServicePlanFeatures)
            End If

            'Check if this feature has Children
            If feature.Children Is Nothing OrElse feature.Children.Count = 0 Then
                'If yes and if the list does not have this ID yet, create one
                If Not serviceFeatureList.ContainsKey(serviceID) Then
                    serviceFeatureList.Add(serviceID, New ServicePlanFeatures())
                End If
                'Associate Feature to Service plan
                serviceFeatureList(serviceID).AddFeature(feature.ID, "0")
            Else
                'If the feature has children
                'If yes and if the list does not have this ID yet, create one
                If Not serviceFeatureList.ContainsKey(serviceID) Then
                    serviceFeatureList.Add(serviceID, New ServicePlanFeatures())
                End If
                ''Associate Feature to Service plan
                'serviceFeatureList(serviceID).AddFeature(feature.ID, 0)

                'Check if the parent ID (placeholders) is already added, if not, add to the list
                If Not serviceFeatureList(serviceID).ParentList.ContainsKey(feature.ID) Then
                    Dim objParent As New Parent(CType(feature, BLFeature).MinChoiceSelection, CType(feature, BLFeature).MaxChoiceSelection, CType(feature, BLFeature).MinChoiceSelection, CType(feature, BLFeature).MaxChoiceSelection)
                    serviceFeatureList(serviceID).AddParent(feature.ID, objParent)
                End If
                'Loop through all choices and asoociate to the service plan
                For Each objChoice As BLFeature In feature.Children.Values
                    If Not serviceFeatureList(serviceID).FeatureList.ContainsKey(objChoice.ID) Then
                        serviceFeatureList(serviceID).AddFeature(objChoice.ID, feature.ID)
                    End If
                Next
            End If
        Catch ex As Exception
            Throw New ApplicationException("Cannot build service plan feature object required to find a service plan")
        End Try
    End Sub

    'Form a custom Feature List of IDs and deciding attributes associated with every Serviceplan 
    ' to help form a Service plan based on Customizations in the cart
    Private Sub AddToServiceCustomizations(ByVal feature As ISubCartItem, ByVal serviceID As String)
        'Instantiate if not available
        'If serviceFeatureList Is Nothing Then
        '  serviceFeatureList = New Dictionary(Of String, ServicePlanFeatures)
        'End If

        ''Check if this Customization has Children
        'If feature.Children Is Nothing OrElse feature.Children.Count = 0 Then
        '  'If yes and if the list does not have this ID yet, create one
        '  If Not serviceFeatureList.ContainsKey(serviceID) Then
        '    serviceFeatureList.Add(serviceID, New ServicePlanFeatures())
        '  End If
        '  'Associate Customization to Service plan
        '  serviceFeatureList(serviceID).AddCustomization(feature.ID, 0)
        'Else
        '  'If the Customization has children
        '  'If yes and if the list does not have this ID yet, create one
        '  If Not serviceFeatureList.ContainsKey(serviceID) Then
        '    serviceFeatureList.Add(serviceID, New ServicePlanFeatures())
        '  End If
        '  ''Associate Customization to Service plan
        '  'serviceFeatureList(serviceID).AddCustomization(feature.ID, 0)

        '  'Check if the parent ID (placeholders) is already added, if not, add to the list
        '  If Not serviceFeatureList(serviceID).ParentList.ContainsKey(CInt(feature.ID)) Then
        '    Dim objParent As New Parent(CType(feature, Customization).MinChoiceSelection, CType(feature, Customization).MaxChoiceSelection, CType(feature, Customization).MinChoiceSelection, CType(feature, Customization).MaxChoiceSelection)
        '    serviceFeatureList(serviceID).AddParent(CInt(feature.ID), objParent)
        '  Else
        '    'If Parent already exists, adjust the Max selection as customization has max count differrnt from Placeholder
        '    Dim objParent As Parent = serviceFeatureList(serviceID).ParentList(CInt(feature.ID))
        '    objParent.Max = CType(feature, Customization).MaxChoiceSelection + objParent.Max
        '  End If
        '  'Loop through all choices and asoociate to the service plan
        '  For Each objChoice As Feature In feature.Children.Values
        '    serviceFeatureList(serviceID).AddCustomization(objChoice.ID, CInt(feature.ID))
        '  Next
        'End If

    End Sub

    ' gets the user selected cart items as a list
    Private Function GetCartItemsWithcategory() As Dictionary(Of String, CartSelections)
        Dim list As New Dictionary(Of String, CartSelections)
        Dim objCartSelection As CartSelections
        For Each item As ICartItem In catalog.Cart.CartItems.Values
            If item.Type = ItemType.Bundle Then
                objCartSelection.Category = item.Category
                objCartSelection.FeatureType = FeatureType.NotSpecified
                list.Add(item.ID, objCartSelection)
                For Each sp As BLServicePlan In item.Children.Values
                    AddSelectedServicePlan(sp, list)
                Next
            ElseIf item.Type = ItemType.ServicePlan Then
                Dim sp As BLServicePlan = DirectCast(item, BLServicePlan)
                AddSelectedServicePlan(sp, list)
            End If
        Next
        Return list
    End Function

    ' adds user selected service plan and its children to the list
    Private Sub AddSelectedServicePlan(ByVal sp As BLServicePlan, ByVal list As Dictionary(Of String, CartSelections))

        Dim objCartSelection As CartSelections

        If sp.IsSelected Then
            objCartSelection.Category = sp.Category
            objCartSelection.FeatureType = FeatureType.NotSpecified
            list.Add(sp.ID, objCartSelection)
        End If

        For Each feature As ISubCartItem In sp.Features.Values
            objCartSelection.Category = feature.Category
            objCartSelection.FeatureType = feature.FeatureType
            If feature.Children Is Nothing OrElse feature.Children.Count = 0 Then
                If feature.IsSelected Then
                    list.Add(feature.ID, objCartSelection)
                End If
            End If
            For Each choice As ISubCartItem In feature.Children.Values
                If choice.IsSelected Then
                    objCartSelection.Category = feature.Category
                    objCartSelection.FeatureType = feature.FeatureType
                    If Not list.ContainsKey(choice.ID) Then list.Add(choice.ID, objCartSelection)
                End If
            Next
        Next

    End Sub

    'for a given feature finds conflicting features if any, and removes those conflicting features.
    Private Function RemoveConflictingFeatures(ByVal featureID As String, ByVal userSelectionList As Dictionary(Of String, CartSelections)) As String
        Try
            Dim conflictingFeatures As List(Of String)
            conflictingFeatures = rules.GetConflictingFeatures(featureID)
            If Not conflictingFeatures Is Nothing Then
                For Each id As String In conflictingFeatures
                    If userSelectionList.ContainsKey(id) Then
                        userSelectionList.Remove(id)
                        Return id
                        Exit For
                    End If
                Next
            End If
            Return Nothing
        Catch ex As Exception
            Throw New ApplicationException("Cannot perform conflicting features operation", ex)
        End Try
    End Function

    Private Function FindServicePlanInCartByCategory(ByVal category As Category) As String
        For Each item As ICartItem In catalog.Cart.CartItems.Values
            If item.Type = ItemType.Bundle Then
                For Each sp As BLServicePlan In item.Children.Values
                    If sp.Category = category Then
                        Return sp.ID
                    End If
                Next
            Else
                If item.Type = ItemType.ServicePlan Then
                    If item.Category = category Then
                        Return item.ID
                    End If
                End If
            End If
        Next
        Return Nothing
    End Function

    Private Sub RefreshFeatureList()
        Try
            If featureList Is Nothing Then Exit Sub
            For Each f As BLFeature In featureList.Values
                Dim objfeature As ISubCartItem = CType(catalog.Cart, BLShoppingCart).ContainsThisFeature(f.ID)
                If Not objfeature Is Nothing Then
                    If Not receivers Is Nothing Then
                        If objfeature.ID = BLCommon.GetKey(BLCommon.Receivers.RECEIVER, receivers) Or objfeature.ID = BLCommon.GetKey(BLCommon.Receivers.HD, receivers) Then
                            f.IsAvailable = True
                        Else
                            f.IsAvailable = objfeature.IsAvailable
                            f.ISSelected = objfeature.IsSelected
                        End If
                    Else
                        f.IsAvailable = objfeature.IsAvailable
                        f.ISSelected = objfeature.IsSelected
                    End If

                Else
                    f.IsAvailable = True
                End If
            Next
        Catch ex As Exception
            Throw New ApplicationException("cannot refresh feature list", ex)
        End Try
    End Sub


    ''' <summary>
    ''' Adds a choice to Option of a ServicePlan in the Shopping Cart.
    ''' </summary>
    ''' <param name="itemID">Id of the Choice to be Added.</param>
    ''' <param name="Quantity">Number of above feature to be added.</param>
    ''' <remarks>
    ''' Finds Feature(choice) with the given ID,Adds this feature to UserSelectionList.
    ''' Refreshes the Catalog with this new selection to option.
    ''' Updates Cart Price.
    ''' After all the changes adds CatalogManager to session.
    ''' </remarks>
    Public Overrides Sub AddOption(ByVal trackID As String, ByVal itemID As String, Optional ByVal Quantity As Integer = Nothing)

        Try
            PopulateLocalVariables(trackID)
            AddAnOption(itemID, Quantity)
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot add an option at this time", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try

    End Sub

    Private Sub AddAnOption(ByVal itemID As String, Optional ByVal Quantity As Integer = Nothing)

        Dim item As ISubCartItem
        Dim objCartSelection As CartSelections
        Dim cartItemsWithCategory As Dictionary(Of String, CartSelections)

        cartItemsWithCategory = GetCartItemsWithcategory()

        If cartItemsWithCategory Is Nothing Then
            cartItemsWithCategory = New Dictionary(Of String, CartSelections)
        End If

        item = CType(catalog.Cart, BLShoppingCart).GetParentFeature(itemID)
        If item Is Nothing Then Exit Sub
        objCartSelection.Category = item.Category
        objCartSelection.FeatureType = item.FeatureType

        If Not cartItemsWithCategory.ContainsKey(itemID) Then cartItemsWithCategory.Add(itemID, objCartSelection)

        If Quantity = Nothing Then
            'TODo: review this
            UpdateSelectedChoices(CType(item, BLFeature), itemID, True, cartItemsWithCategory)
        Else
            If Not item.Children Is Nothing AndAlso item.Children.Count > 0 Then
                CType(item, BLFeature).QuantitySelected = Quantity
            Else
                UpdateSelectedChoices(CType(item, BLFeature), itemID, True, cartItemsWithCategory)
            End If
        End If

        catalog.RefreshFeature(CType(item, BLFeature), False, True, cartItemsWithCategory)
        'To update prices
        sCart.UpdateCartItemsPrice()

        SetSession(CatalogManagerKey, Me.ValuesForSetSession)

    End Sub

    Public Overrides Function AddSubcartItem(ByVal trackingid As String, ByVal itemID As String, ByVal Quantity As Integer) As INotification
        Try
            If trackingid IsNot Nothing Then
                PopulateLocalVariables(trackingid)
            End If
            ' returning after order is submitted
            If catalog.Cart.Submitted Then
                ClearShoppingCart(trackingid)
                CType(catalog.Cart, BLShoppingCart).OrderSubmitted = False
            End If

            Dim item As ISubCartItem
            Dim objCartSelection As CartSelections
            Dim cartItemsWithCategory As Dictionary(Of String, CartSelections)

            cartItemsWithCategory = GetCartItemsWithcategory()

            If cartItemsWithCategory Is Nothing Then
                cartItemsWithCategory = New Dictionary(Of String, CartSelections)
            End If

            Dim sp As BLServicePlan
            featureList.TryGetValue(itemID, item)
            For Each objitem As ICartItem In catalog.Cart.CartItems.Values
                If objitem.Type = ItemType.Bundle Then
                    For Each objsubitem As ISubCartItem In objitem.Children.Values
                        If objsubitem.Category = item.Category Then
                            sp = CType(objsubitem, BLServicePlan)
                            Exit For
                        End If
                    Next
                Else
                    If objitem.Category = item.Category Then
                        sp = CType(objitem, BLServicePlan)
                        Exit For
                    End If
                End If
            Next

            If Not sp Is Nothing AndAlso sp.Features.ContainsKey(itemID) Then
                Dim f As BLFeature = DirectCast(sp.Features(itemID), BLFeature)
                If f Is Nothing Then Return New Notification(NotificationAction.Add, "Item Not Found", NotificationCode.CannotAddCustomization)
                objCartSelection.Category = f.Category
                objCartSelection.FeatureType = f.FeatureType
                _message = New Notification(NotificationAction.Add, f.Name, NotificationCode.Success)


                CType(f, BLFeature).QuantitySelected = Quantity
                If Quantity = 0 Then
                    cartItemsWithCategory.Remove(itemID)
                    catalog.RefreshFeature(CType(f, BLFeature), True, False, cartItemsWithCategory)
                Else
                    If Not cartItemsWithCategory.ContainsKey(itemID) Then cartItemsWithCategory.Add(itemID, objCartSelection)
                    catalog.RefreshFeature(CType(f, BLFeature), False, True, cartItemsWithCategory)
                End If

                RefreshFeatureList()
                'To update prices
                sCart.UpdateCartItemsPrice()
            Else
                Return New Notification(NotificationAction.Add, "Item Not Found", NotificationCode.CannotAddCustomization)
            End If
            SetSession(CatalogManagerKey, Me.ValuesForSetSession)

            Return _message
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot add feature with quantity to cart", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try
    End Function

    Public Overrides Function AddSubcartItem(ByVal trackingid As String, ByVal itemID As String, ByVal TextEntry As String) As INotification
        Try
            If trackingid IsNot Nothing Then
                PopulateLocalVariables(trackingid)
            End If
            ' returning after order is submitted
            If catalog.Cart.Submitted Then
                ClearShoppingCart(trackingid)
                CType(catalog.Cart, BLShoppingCart).OrderSubmitted = False
            End If

            Dim item As ISubCartItem
            Dim objCartSelection As CartSelections
            Dim cartItemsWithCategory As Dictionary(Of String, CartSelections)

            cartItemsWithCategory = GetCartItemsWithcategory()

            If cartItemsWithCategory Is Nothing Then
                cartItemsWithCategory = New Dictionary(Of String, CartSelections)
            End If

            featureList.TryGetValue(itemID, item)

            Dim sp As BLServicePlan
            featureList.TryGetValue(itemID, item)
            For Each objitem As ICartItem In catalog.Cart.CartItems.Values
                If objitem.Type = ItemType.Bundle Then
                    For Each objsubitem As ISubCartItem In objitem.Children.Values
                        If objsubitem.Category = item.Category Then
                            sp = CType(objsubitem, BLServicePlan)
                            Exit For
                        End If
                    Next
                Else
                    If objitem.Category = item.Category Then
                        sp = CType(objitem, BLServicePlan)
                        Exit For
                    End If
                End If
            Next

            If Not sp Is Nothing AndAlso sp.Features.ContainsKey(itemID) Then
                Dim f As BLFeature = DirectCast(sp.Features(itemID), BLFeature)
                If f Is Nothing Then Return New Notification(NotificationAction.Add, "Item Not Found", NotificationCode.CannotAddCustomization)
                objCartSelection.Category = f.Category
                objCartSelection.FeatureType = f.FeatureType
                _message = New Notification(NotificationAction.Add, f.Name, NotificationCode.Success)


                If f Is Nothing Then Return New Notification(NotificationAction.Add, "Item Not Found", NotificationCode.CannotAddCustomization)
                objCartSelection.Category = item.Category
                objCartSelection.FeatureType = item.FeatureType
                _message = New Notification(NotificationAction.Add, item.Name, NotificationCode.Success)


                CType(f, BLFeature).Text = TextEntry
                If TextEntry.Equals(String.Empty) Then
                    If cartItemsWithCategory.ContainsKey(itemID) Then cartItemsWithCategory.Remove(itemID)
                    catalog.RefreshFeature(CType(f, BLFeature), True, False, cartItemsWithCategory)
                Else
                    If Not cartItemsWithCategory.ContainsKey(itemID) Then cartItemsWithCategory.Add(itemID, objCartSelection)
                    catalog.RefreshFeature(CType(f, BLFeature), False, True, cartItemsWithCategory)
                End If

                RefreshFeatureList()
                'To update prices
                sCart.UpdateCartItemsPrice()
            Else
                Return New Notification(NotificationAction.Add, "Item Not Found", NotificationCode.CannotAddCustomization)
            End If
            SetSession(CatalogManagerKey, Me.ValuesForSetSession)

            Return _message
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot add feature with text entry to cart", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try
    End Function

    ''' <summary>
    ''' Removes a choice from Option of a ServicePlan in the Shopping Cart.
    ''' </summary>
    ''' <param name="itemID">Id of the Choice to be Removed.</param>
    ''' <remarks>
    ''' Finds Feature(choice) with the given ID,Removes this feature from UserSelectionList.
    ''' Refreshes the Catalog with this UserSelectionList.
    ''' Updates Cart Price.
    ''' After all these changes, adds CatalogManager to session.
    ''' </remarks>
    Public Overrides Sub RemoveOption(ByVal trackID As String, ByVal itemID As String)

        Dim item As ISubCartItem
        Try
            PopulateLocalVariables(trackID)
            Dim cartItemsWithCategory As Dictionary(Of String, CartSelections)

            cartItemsWithCategory = GetCartItemsWithcategory()

            If cartItemsWithCategory.ContainsKey(itemID) Then
                cartItemsWithCategory.Remove(itemID)
            End If

            item = CType(catalog.Cart, BLShoppingCart).GetParentFeature(itemID)
            If item Is Nothing Then Exit Try

            'TODo: review this
            UpdateSelectedChoices(CType(item, BLFeature), itemID, False, cartItemsWithCategory)

            catalog.RefreshFeature(CType(item, BLFeature), True, False, cartItemsWithCategory)
            'To update prices
            sCart.UpdateCartItemsPrice()

            SetSession(CatalogManagerKey, Me.ValuesForSetSession)
        Catch ex As ApplicationException
            BLCommon.LogException(ex, ExceptionSeverity.Catastrophic)
            Throw ex
        Catch ex As Exception
            Dim aex As New ApplicationException("Cannot remove a feature from Cart", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Catastrophic)
            Throw aex
        End Try

    End Sub

    Private Sub ClearUnDoStack()
        If Not _undoremove Then
            'Set Undo /Remove to False as user just added items to cart as this functionality is available only when the last action is an "Add Cart"
            sCart.m_undo = False

            'If not initialized, then instantiate it
            If UndoStack Is Nothing Then
                UndoStack = New Stack(Of Items)
            End If
            'Adding an item to cart should reset the stack.
            UndoStack.Clear()
        End If
    End Sub


    Private Function CreateUnDoStackItem(ByVal cartItem As ICartItem) As Items
        Dim item As Items
        Dim subItem As Items
        Dim subItems As New Dictionary(Of String, Items)
        Dim quantity As Integer
        Try
            If cartItem.Type = ItemType.Bundle Then
                For Each subCartItem As BLServicePlan In cartItem.Children.Values
                    For Each feature As BLFeature In subCartItem.Features.Values
                        For Each choice As BLFeature In feature.Choices.Values
                            If choice.ISSelected Then
                                If subItems.ContainsKey(choice.ID) Then
                                    quantity = subItems(choice.ID).Number
                                    If quantity = 0 Then
                                        quantity = 2
                                    Else : quantity += 1
                                    End If
                                    subItems(choice.ID).Number = quantity
                                Else
                                    subItem = New Items(choice.ID, choice.Description, GwyItemType.Choice)
                                    subItems.Add(subItem.ID, subItem)
                                End If
                            End If
                        Next
                    Next
                Next
            Else
                For Each subCartItem As BLFeature In cartItem.Children.Values
                    For Each choice As BLFeature In subCartItem.Choices.Values
                        If choice.ISSelected Then
                            subItem = New Items(choice.ID, choice.Description, GwyItemType.Choice)
                            subItems.Add(subItem.ID, subItem)
                        End If
                    Next
                Next
            End If

            Dim type As GwyItemType
            If cartItem.Type = ItemType.Bundle Then
                type = GwyItemType.Bundle
            Else
                type = GwyItemType.ServicePlan
            End If
            item = New Items(cartItem.ID, cartItem.Description, type, Nothing, Nothing, subItems)
            Return item
        Catch ex As Exception
            Throw New ApplicationException("Error creating undo stack", ex)
        End Try
    End Function

    Private Function CreateUnDoStackItem(ByVal f As BLFeature) As Items
        Return New Items(f.ID, f.Description, GwyItemType.Choice)
    End Function

    Private Sub PushToUnDoStack(ByVal item As Items)
        'Set Undo /Remove to true as user just removed from cart
        sCart.m_undo = True

        'If not initialized, then instantiate it
        If UndoStack Is Nothing Then
            UndoStack = New Stack(Of Items)
        End If


        'Add the last removed item to stack.
        UndoStack.Push(item)
    End Sub

#End Region

#Region "Bundling fucntions"

    Private Sub CheckForCategory(ByVal list As Dictionary(Of String, CartSelections), ByVal item As ICartItem)
        Try
            For Each ID As String In list.Keys
                If list(ID).Category = item.Category Then
                    If Not ID = item.ID AndAlso CType(Left(ID, 1), ItemType) = ItemType.ServicePlan Then
                        'To check if service plan is directly present in the cart and or as part of a Bundle
                        Dim oldSP As BLServicePlan
                        If Not catalog.Cart.CartItems.ContainsKey(ID) Then
                            For Each i As ICartItem In catalog.Cart.CartItems.Values
                                If i.Type = ItemType.Bundle Then
                                    oldSP = CType(i.Children(ID), BLServicePlan)
                                    Exit For
                                End If
                            Next
                        Else
                            oldSP = CType(catalog.Cart.CartItems(ID), BLServicePlan)
                        End If
                        UpdateSelectedChoices(oldSP, item)
                        If catalog.Cart.CartItems.ContainsKey(ID) Then
                            RemoveItemFromCart(ID, Nothing)
                        End If
                        'Remove from the temporary list to reflect in the cart
                        list.Remove(ID)
                        _message.SetMessageResult(oldSP.Description, item.Name, NotificationCode.ChangeServicePlan, NotificationSeverity.IsMessage)

                        Exit Sub
                    End If
                End If
            Next
        Catch ex As Exception
            Throw New ApplicationException("Error removing service plan conflicting with added service plan", ex)
        End Try
    End Sub

    ' dynamically bundles the srvice plans selected .
    Private Sub DynamicBundle(ByVal item As ICartItem, ByVal userSelections As Dictionary(Of String, CartSelections))
        Try
            Dim cart As BLShoppingCart = sCart
            If item.Type = ItemType.ServicePlan Then
                If Not (userSelections Is Nothing OrElse userSelections.Values.Count = 0) Then
                    Dim bundleID As String = Bundled(item, userSelections)
                    If Not bundleID Is Nothing Then
                        Dim bundle As BLBundle = DirectCast(catalog.Bundles(bundleID), BLBundle)
                        If Not bundle Is Nothing Then
                            ' bundle is found 
                            If cart.CartItems.ContainsKey(bundleID) Then
                                ' this bundle is already in the cart, so no need to add bundle to cart . Just refresh bundle selections
                                'UpdateSelectedChoices(CType(item, BLServicePlan), CType(bundle.ServicePlans(item.ID), BLServicePlan))
                                catalog.Refresh(bundle, False, True, userSelections)
                                'RefreshFeatureList(bundle)
                            Else
                                ' this bundle is not in cart
                                For Each i As ICartItem In bundle.ServicePlans.Values
                                    'remove service plans which can be part of this bundle from cart(when a bundle is added these service plans will be part of the bundle)
                                    If i.Type = ItemType.ServicePlan And bundle.ServicePlans.ContainsKey(i.ID) Then
                                        ' UpdateSelectedChoices(CType(catalog.Cart.CartItems(i.ID), BLServicePlan), CType(bundle.ServicePlans(i.ID), BLServicePlan))
                                        RemoveItemFromCart(i.ID, userSelections)
                                    End If
                                Next
                                ' add bundle to cart
                                AddItemToCart(bundle, userSelections, False)
                                _message.SetMessageResult(String.Empty, bundle.Name, NotificationCode.NewBundle, NotificationSeverity.IsMessage)

                            End If
                        End If
                    Else
                        ' bundle is not found with the existing cart items
                        If cart.CartItems.Count > 0 Then
                            RemoveBundle(userSelections, False)
                        End If
                    End If
                End If
            End If
        Catch ex As Exception
            Throw New ApplicationException("Cannot bundle service plans", ex)
        End Try
    End Sub

    ' finds the appropriate bundle for the selected service plans in cart
    Private Function Bundled(ByVal item As ICartItem, ByVal userSelections As Dictionary(Of String, CartSelections)) As String
        Dim matched As Boolean = False
        Dim totalMatch As Integer
        Dim bundleList As New Dictionary(Of String, Integer)
        For Each b As ICartItem In catalog.Bundles.Values
            totalMatch = 0
            For Each sp As ISubCartItem In b.Children.Values
                matched = False
                For Each itemID As String In userSelections.Keys
                    'If cartItem.Type = ItemType.ServicePlan Then
                    If itemID = sp.ID Then
                        matched = True
                        totalMatch += 1
                        Exit For ' found an equivalent service plan, so move to next servce plan
                    Else
                        matched = False
                    End If
                    'End If
                Next
                ' this service plan is not in shopping cart, stop here and move to next bundle.
                If matched = False Then
                    Exit For
                End If
            Next
            ' found a matching bundle, stop searching
            If matched = True Then
                bundleList.Add(b.ID, totalMatch)
                'Return "Bundle Found" & b.Description
            End If
        Next
        Return GetBundleCodeFromList(bundleList)
    End Function

    ' removes bundle from cart and adds all the userselected service plans to the cart
    Private Sub RemoveBundle(ByVal userSelections As Dictionary(Of String, CartSelections), ByVal bundle As Boolean)
        For Each ci As ICartItem In catalog.Cart.CartItems.Values
            If ci.Type = ItemType.Bundle Then

                ' there is an old bundle in cart, remove that bundle
                RemoveItemFromCart(ci.ID, userSelections)

                ' set cart notification message
                _message.SetMessageResult(ci.Description, String.Empty, NotificationCode.RemoveBundle, NotificationSeverity.IsMessage)

                'since bundle is removed from cart, service plans which are part of bundle and are in user selection list, add to cart
                For Each si As ISubCartItem In ci.Children.Values
                    If userSelections.ContainsKey(si.ID) Then
                        ' move choice selections to these new service plans
                        'UpdateSelectedChoices(CType(si, BLServicePlan), catalog.ServicePlans(si.ID))
                        AddItemToCart(catalog.ServicePlans(si.ID), userSelections, bundle)
                    End If
                Next
                Exit For
            End If
        Next
    End Sub

    ' returns bundle(id) which matches maximum number of service plans in cart
    Private Function GetBundleCodeFromList(ByVal bundleList As Dictionary(Of String, Integer)) As String
        Dim matchNumber As Integer
        Dim totalMatch As Integer = 0
        Dim bundleID As String
        If Not bundleList.Count = 0 Then
            For Each id As String In bundleList.Keys
                matchNumber = bundleList(id)
                If totalMatch < matchNumber Then
                    totalMatch = matchNumber
                    bundleID = id
                End If
            Next
        End If
        Return bundleID
    End Function

#End Region

#Region "Rules"

    ' given a particular sub cart item finds the appropriate service plan for that item by applying all the rules.
    Private Function FindServicePlan(ByVal featureCategory As Category, ByVal userSelectionList As Dictionary(Of String, CartSelections)) As BLServicePlan

        'declaration for separate lists to maintain Included features / Customizations match
        Dim matchedServicePlanFeatures As New Dictionary(Of String, Integer)
        Dim matchedServicePlanCustomizations As New Dictionary(Of String, Integer)

        'create a custom list which is filtered by the added / removed Item category or Line Of business
        Dim userSelectionByCategory As New Dictionary(Of String, Category)
        Try
            For Each c As String In userSelectionList.Keys
                If userSelectionList(c).Category.Equals(featureCategory) Then
                    If Not userSelectionByCategory.ContainsKey(c) Then
                        userSelectionByCategory.Add(c, featureCategory)
                    End If
                End If
            Next

            'Loop through the pre-generated Service Plan feature list which contains association of Features / Customizations
            'with a service plan
            For Each ID As String In serviceFeatureList.Keys
                'For Every Service Plan in the list, compare against the cart Items list
                For Each featureID As String In userSelectionByCategory.Keys
                    'If the cart item is a feature
                    If serviceFeatureList(ID).FeatureList.ContainsKey(featureID) Then
                        'If cart item is default feature (parent ID is Zero) and not a place-holder
                        If serviceFeatureList(ID).FeatureList(featureID) = "0" Then
                            'Increment / add the matched feature count for the corresponding service plan
                            If Not matchedServicePlanFeatures.ContainsKey(ID) Then
                                matchedServicePlanFeatures.Add(ID, 1)
                            Else
                                matchedServicePlanFeatures(ID) = matchedServicePlanFeatures(ID) + 1
                            End If
                        Else
                            'If cart item is a place-holder, refer to the parent and based on the Minimum selection allowed,
                            'it is determined if the Item is a place holder item or not
                            Dim objParent As Parent = serviceFeatureList(ID).ParentList(serviceFeatureList(ID).FeatureList(featureID))
                            If objParent.Min > 0 Then

                                objParent.Min = objParent.Min - 1
                                objParent.Max = objParent.Max - 1

                                'Increment / add the matched feature count for the corresponding service plan
                                If matchedServicePlanFeatures.ContainsKey(ID) Then
                                    matchedServicePlanFeatures(ID) = matchedServicePlanFeatures(ID) + 1
                                Else
                                    matchedServicePlanFeatures.Add(ID, 1)
                                End If
                            ElseIf objParent.Max > 0 Then

                                objParent.Min = objParent.Min - 1
                                objParent.Max = objParent.Max - 1

                                'Increment / add the matched feature count for the corresponding service plan
                                If matchedServicePlanFeatures.ContainsKey(ID) Then
                                    matchedServicePlanFeatures(ID) = matchedServicePlanFeatures(ID) + 1
                                Else
                                    matchedServicePlanFeatures.Add(ID, 1)
                                End If

                            End If

                        End If

                    End If
                Next
                're-set Min / Max count of parent list
                For Each objParent As Parent In serviceFeatureList(ID).ParentList.Values
                    objParent.Min = objParent.AllowedMin
                    objParent.Max = objParent.Allowedmax
                Next

            Next

            'Call Matching logic to find the Service plan which is best match based on the Pre-defined rules
            Dim retID As Integer = GetServicePlanFromMatches(matchedServicePlanFeatures, matchedServicePlanCustomizations)
            If retID <> 0 Then
                Return DirectCast(catalog.ServicePlans(CStr(retID)), BLServicePlan)
            End If

            Return Nothing
        Catch ex As Exception
            Throw New ApplicationException("Cannot find a service plan from selected features", ex)
        End Try
    End Function

    Private Function GetServicePlanFromMatches(ByVal matchedServicePlanFeatures As Dictionary(Of String, Integer), ByVal matchedServicePlanCustomizations As Dictionary(Of String, Integer)) As Integer

        Dim maxMatch As Integer = 0
        Dim maxID As Integer

        'Loop through all Feature macth lists
        For Each id As String In matchedServicePlanFeatures.Keys
            'If the current feature match count is more than the previous feature match count, then set match id with the current one
            If maxMatch < matchedServicePlanFeatures(id) Then
                maxMatch = matchedServicePlanFeatures(id)
                maxID = CInt(id)
                'If the feature match count are equal with previous
            ElseIf maxMatch = matchedServicePlanFeatures(id) Then
                'if the current customization match count is more than previous, then set match id with current one
                Dim intCount As Integer
                Dim intCountMax As Integer

                matchedServicePlanCustomizations.TryGetValue(id, intCount)
                intCount = intCount + matchedServicePlanFeatures(id)

                matchedServicePlanCustomizations.TryGetValue(CStr(maxID), intCount)
                intCountMax = intCountMax + matchedServicePlanFeatures(CStr(maxID))
                If intCount > intCountMax Then
                    maxID = CInt(id)
                Else
                    maxID = CInt(rules.PriorityServicePlan(CStr(maxID), id))
                End If
            End If
        Next

        Return maxID
    End Function

    Public Sub CheckOut(ByVal trackID As String)
        PopulateLocalVariables(trackID)
        Dim userSelection As Dictionary(Of String, CartSelections) = GetCartItemsWithcategory()
        SetDefaults(userSelection)
    End Sub

    ' its not used
    Private Sub SetDefaults(ByRef userSelections As Dictionary(Of String, CartSelections), Optional ByVal sp As BLServicePlan = Nothing)
        Dim defaultChoices As List(Of String) = rules.GetDefaultChoices
        'Dim defaultchoices As New List(Of String)
        'defaultchoices.Add("47")
        ' Dim userselections As Dictionary(Of String, CartSelections) = GetCartItemsWithcategory()
        If sp Is Nothing Then
            For Each cItem As ICartItem In catalog.Cart.CartItems.Values
                If cItem.Type = ItemType.Bundle Then
                    For Each sItem As BLServicePlan In cItem.Children.Values
                        SetDefaults(userSelections, sItem)
                    Next
                ElseIf cItem.Type = ItemType.ServicePlan Then
                    SetDefaults(userSelections, CType(cItem, BLServicePlan))
                End If
            Next
        Else
            Dim selection As CartSelections
            For Each f As BLFeature In sp.Features.Values
                For Each choice As BLFeature In f.Choices.Values
                    If defaultChoices.Contains(choice.ID) Then
                        f.ChoicesSelection.Add(choice.ID)
                        selection.Category = choice.Category
                        selection.FeatureType = FeatureType.IsPlaceholder
                        userSelections.Add(choice.ID, selection)
                        catalog.RefreshFeature(f, False, True, userSelections)
                        Exit For
                    End If
                Next
            Next
        End If
    End Sub
    ' not being used
    Private Sub ConfigureOrderLevelFeatures()
        Dim features As Dictionary(Of String, Rules.ExceptionalBehavior) = rules.GetExceptionalFeatures
        For Each ex As Rules.ExceptionalBehavior In features.Values
            If ex.Action = ExceptionalAction.OnePerOrder Then
                ' this implementation depends on how we are going to provide UI the display information.
            End If
        Next
    End Sub

    Public Overrides Function GetChooseOptionsXml(ByVal trackingid As String) As String
        PopulateLocalVariables(trackingid)
        Dim iProvider As IG2BServicesProvider = CType(Activator.GetObject(GetType(IG2BServicesProvider), CStr(HttpContext.Current.Application("RemoteURL_G2BServicesProvider"))), IG2BServicesProvider)
        Try
            Dim objresult As EntityG2BServices.EntityUIRules = CType(iProvider.GetChooseOptionsXml(), EntityG2BServices.EntityUIRules)
            If Not objresult.Exception Then
                Return objresult.Data
            Else
                BLCommon.LogException(New Exception("catalog Manager - Get Choose options xml failed as:" & objresult.ExceptionMessage & " - " & objresult.ExceptionStackTrace), ExceptionSeverity.Fatal)
                Return Nothing
            End If
        Catch ex As Exception
            Dim aex As New ApplicationException("catalog Manager - Get Choose options xml failed", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Fatal)
            Throw aex
        Finally
            iProvider = Nothing
        End Try
    End Function

    Public Overrides Function GetBuildYourOwnXml(ByVal trackingid As String) As String
        PopulateLocalVariables(trackingid)
        Dim iProvider As IG2BServicesProvider = CType(Activator.GetObject(GetType(IG2BServicesProvider), CStr(HttpContext.Current.Application("RemoteURL_G2BServicesProvider"))), IG2BServicesProvider)
        Try
            Dim objresult As EntityG2BServices.EntityUIRules = CType(iProvider.GetBuildYourOwnXml(), EntityG2BServices.EntityUIRules)
            If Not objresult.Exception Then
                Return objresult.Data
            Else
                BLCommon.LogException(New Exception("catalog Manager - Get Build Your Own xml failed as:" & objresult.ExceptionMessage & " - " & objresult.ExceptionStackTrace), ExceptionSeverity.Fatal)
                Return Nothing
            End If
        Catch ex As Exception
            Dim aex As New ApplicationException("catalog Manager - Get Build Your Own xml failed ", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Fatal)
            Throw aex
        Finally
            iProvider = Nothing
        End Try
    End Function

    Public Overrides Function GetShowPriceList(ByVal trackingid As String) As List(Of String)
        PopulateLocalVariables(trackingid)
        Dim iProvider As IG2BServicesProvider = CType(Activator.GetObject(GetType(IG2BServicesProvider), CStr(HttpContext.Current.Application("RemoteURL_G2BServicesProvider"))), IG2BServicesProvider)
        Try
            Dim objresult As EntityG2BServices.EntityUIRules = CType(iProvider.GetShowPriceList(), EntityG2BServices.EntityUIRules)
            If Not objresult.Exception Then
                Dim doc As New XmlDocument
                doc.LoadXml(objresult.Data.ToString)
                Dim idlist As New List(Of String)
                For Each pageNode As XmlNode In doc.ChildNodes
                    For Each node As XmlNode In pageNode.ChildNodes
                        If node.Attributes("id") IsNot Nothing Then
                            idlist.Add(node.Attributes("id").Value)
                        End If
                    Next
                Next
                Return idlist
            Else
                BLCommon.LogException(New Exception("catalog Manager - GetShowPriceList xml failed as:" & objresult.ExceptionMessage & " - " & objresult.ExceptionStackTrace), ExceptionSeverity.Fatal)
                Return Nothing
            End If
        Catch ex As Exception
            Dim aex As New ApplicationException("catalog Manager - GetShowPriceList failed", ex)
            BLCommon.LogException(aex, ExceptionSeverity.Fatal)
            Throw aex
        Finally
            iProvider = Nothing
        End Try
    End Function

#End Region

End Class

