[FormValueRequired("updatebids")]       //NJM: this comes from the submit button id
        public ActionResult UpdateMyBids(FormCollection form)
        {
            //TODO: Mybids post permission
            //if (!_permissionService.Authorize(StandardPermissionProvider.EnableWishlist))
            //    return RedirectToRoute("HomePage");

            //var cart = _workContext.CurrentCustomer.ShoppingCartItems
            //    .Where(sci => sci.ShoppingCartType == ShoppingCartType.Wishlist)
            //    .LimitPerStore(_storeContext.CurrentStore.Id)
            //    .ToList();

            //var allIdsToRemove = form["removefromcart"] != null
            //    ? form["removefromcart"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
            //    .Select(int.Parse)
            //    .ToList()
            //    : new List<int>();


            Customer customer =  _workContext.CurrentCustomer;
            if (customer == null)                   //can only show bids for signed in customer
                return RedirectToRoute("HomePage");



            //TODO Cache this and make extension/function
            DateTime nullDate = Convert.ToDateTime("01/01/0001");
            DateTime currTime = DateTime.UtcNow;

            var query = from b in _bidhistoryRepo.Table
                        join s in _saleRepo.Table on b.AUSaleId equals s.AUSaleID
                        where s.SaleIsPublished
                        && s.SaleStartDateTime != nullDate
                        && s.SaleEndDateTime != nullDate
                        && s.SaleStartDateTime < currTime
                        && s.SaleEndDateTime > currTime
                        && b.BidderId == customer.Id    //TODO: customer.Id?? see Headerlinks()
                        group b by b.AUProductId
                            into bGroup
                            select bGroup;


            //need to SelectList key
            List<int> bidProducts = query.Select(b => b.Key).ToList();



            //current warnings <cart item identifier, warnings>
            var innerWarnings = new Dictionary<int, IList<string>>();
            foreach (var p in bidProducts)
            {
                foreach (string formKey in form.AllKeys)
                    if (formKey.Equals(string.Format("itembid{0}", p), StringComparison.InvariantCultureIgnoreCase))
                    {
                        decimal newBid;
                        if (decimal.TryParse(form[formKey], out newBid))
                        {
                            //var currSciWarnings = _shoppingCartService.UpdateShoppingCartItem(_workContext.CurrentCustomer,
                            //    sci.Id, sci.AttributesXml, sci.CustomerEnteredPrice,
                            //    sci.RentalStartDateUtc, sci.RentalEndDateUtc,
                            //    newQuantity, true);


                            var currSciWarnings = new List<string>();
                            var bidEnteryModel = _lotService.GetLotBidEntryModel(p);
                            if (!bidEnteryModel.BiddingIsOpen)
                            {
                                //TODO
                                //currSciWarnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.SelectAttribute"), a2.GetLocalized(a => a.Name)));
                                currSciWarnings.Add("Bidding is no longer open for this lot");
                            }
                            else
                                if (newBid < bidEnteryModel.BiddingIncrement)
                                {
                                    //TODO
                                    //currSciWarnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.SelectAttribute"), a2.GetLocalized(a => a.Name)));
                                    currSciWarnings.Add("Your new bid was not accepted - entered bid must be equal or greater than next minimum bid");
                                }
                                else
                            {

                                int bidResult = _lotService.UpdateLotBid(bidEnteryModel.AUSaleID.GetValueOrDefault(), bidEnteryModel.SaleStoreID.GetValueOrDefault(), p,
                                    newBid, _workContext.CurrentCustomer.Id,bidEnteryModel.BiddingIncrement,bidEnteryModel.ReserveAmt, null);

                                if (bidResult == 99)           //DB update error
                                {
                                    currSciWarnings.Add("We're sorry but your bid entry failed for technical reasons (99). Please try again");
                                }
                                else
                                {
                                    if (bidResult == 98)       //bidder got underbid
                                    {
                                        currSciWarnings.Add("We're sorry but another bid was made while you were reviewing the product. Please try again");
                                    }
                                    else
                                    {
                                        //return 0
                                    }
                                    {
                                        //SuccessNotification("Your bid was entered!");
                                        currSciWarnings.Add("Your bid was entered!");

                                    }
                                }
                            }

                            innerWarnings.Add(p, currSciWarnings);
                        }
                        break;
                    }
            }

            ////updated wishlist%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            //cart = _workContext.CurrentCustomer.ShoppingCartItems
            //    .Where(sci => sci.ShoppingCartType == ShoppingCartType.Wishlist)
            //    .LimitPerStore(_storeContext.CurrentStore.Id)
            //    .ToList();
           
            //var model = new WishlistModel();
            //PrepareWishlistModel(model, cart);
            //update current warnings
            //foreach (var kvp in innerWarnings)
            //{
            //    //kvp = <cart item identifier, warnings>
            //    var sciId = kvp.Key;
            //    var warnings = kvp.Value;
            //    //find model
            //    var sciModel = model.Items.FirstOrDefault(x => x.Id == sciId);
            //    if (sciModel != null)
            //        foreach (var w in warnings)
            //            if (!sciModel.Warnings.Contains(w))
            //                sciModel.Warnings.Add(w);
            //}
            //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

            //NJM: do again in case entered bids in another window
           // DateTime nullDate = Convert.ToDateTime("01/01/0001");
            DateTime currTime2 = DateTime.UtcNow;

            var query2 = from b in _bidhistoryRepo.Table
                        join s in _saleRepo.Table on b.AUSaleId equals s.AUSaleID
                        where s.SaleIsPublished
                        && s.SaleStartDateTime != nullDate
                        && s.SaleEndDateTime != nullDate
                        && s.SaleStartDateTime < currTime
                        && s.SaleEndDateTime > currTime
                        && b.BidderId == customer.Id    //TODO: customer.Id?? see Headerlinks()
                        group b by b.AUProductId
                            into bGroup
                            select bGroup;




            //need to SelectList key
            List<int> bidProducts2 = query2.Select(b => b.Key).ToList();
            //List<int> products = bids.Select(bids.)


            var model = new AUMyBidsModel();


            PrepareMyBidsModel(model, bidProducts2, customer);

            foreach (var kvp in innerWarnings)
            {
                //kvp = <cart item identifier, warnings>
                var pId = kvp.Key;
                var warnings = kvp.Value;
                //find model
                var sciModel = model.Lots.FirstOrDefault(x => x.Id == pId);
                if (sciModel != null)
                    foreach (var w in warnings)
                        if (!sciModel.Warnings.Contains(w))
                            sciModel.Warnings.Add(w);
            }



            return View(model);
        }
        public ActionResult MyBids(Guid? customerGuid)
        {
            //TODO: Implement MyBids security
            //if (!_permissionService.Authorize(StandardPermissionProvider.EnableWishlist))
            //    return RedirectToRoute("HomePage");

            Customer customer = customerGuid.HasValue ?
                _customerService.GetCustomerByGuid(customerGuid.Value)
                : _workContext.CurrentCustomer;
            if (customer == null)                   //can only show bids for signed in customer
                return RedirectToRoute("HomePage");

            
            DateTime nullDate = Convert.ToDateTime("01/01/0001");
            DateTime currTime = DateTime.UtcNow;

            var query = from b in _bidhistoryRepo.Table
                        join s in _saleRepo.Table on b.AUSaleId equals s.AUSaleID
                        where s.SaleIsPublished
                        && s.SaleStartDateTime != nullDate
                        && s.SaleEndDateTime != nullDate
                        && s.SaleStartDateTime < currTime
                        && s.SaleEndDateTime > currTime
                        && b.BidderId == customer.Id    //TODO: customer.Id?? see Headerlinks()
                        group b by b.AUProductId
                            into bGroup
                            select bGroup;




            //need to SelectList key
            List<int> bidProducts = query.Select(b => b.Key).ToList();
            //List<int> products = bids.Select(bids.)

            
            var model = new AUMyBidsModel();

            PrepareMyBidsModel(model, bidProducts, customer, !customerGuid.HasValue);
            return View(model);


        }
        protected virtual void PrepareMyBidsModel(AUMyBidsModel model,
            List<int> bidProducts, Customer customer,  bool isEditable = true)
        {
            if (bidProducts == null)
                throw new ArgumentNullException("bidProducts");

            if (model == null)
                throw new ArgumentNullException("model");


            //load settings for a chosen store scope
            var storeScope = this.GetActiveStoreScopeConfiguration(_storeService, _workContext);
            var AUConsignorSettings = _settings.LoadSetting<Nop.Plugin.Misc.AUConsignor.Domain.AUConsignorSettings>(storeScope);

            AUStoreTypeEnum storeType = (AUStoreTypeEnum)AUConsignorSettings.StoreTypeId;
            model.StoreType = storeType;

            //needed this beyond IsEditable because if don't come in with customer guid from share wishlist email you
            //still don;t want them to enter bids if they're a guest
            if (_workContext.CurrentCustomer.IsGuest())
            {
                model.IsGuest = true;
            }
            else
            {
                model.IsGuest = false;
            }


            model.EmailWishlistEnabled = _shoppingCartSettings.EmailWishlistEnabled;
            model.IsEditable = isEditable;
            model.DisplayAddToCart = _permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart);
            model.DisplayTaxShippingInfo = _catalogSettings.DisplayTaxShippingInfoWishlist;

            if (bidProducts.Count == 0)
                return;

            #region Simple properties

            //var customer = cart.GetCustomer();
            //NJM: changed to pass in parameter

            model.CustomerGuid = customer.CustomerGuid;
            model.CustomerFullname = customer.GetFullName();
            model.ShowProductImages = _shoppingCartSettings.ShowProductImagesOnShoppingCart;
            model.ShowSku = _catalogSettings.ShowProductSku;

            //cart warnings
            //var cartWarnings = _shoppingCartService.GetShoppingCartWarnings(cart, "", false);
            //foreach (var warning in cartWarnings)
            //    model.Warnings.Add(warning);

            #endregion

            #region MyBids items

            foreach (int p in bidProducts)
            {
                var product = _productService.GetProductById(p);
                var bidItemModel = new AUMyBidsModel.MyBidItemItemModel
                {
                    Id = product.Id,
                    //Sku = sci.Product.FormatSku(sci.AttributesXml, _productAttributeParser),
                    Sku = product.Sku,
                    ProductId = product.Id,
                    ProductName = product.GetLocalized(x => x.Name),
                    ProductSeName = product.GetSeName(),
                    //Quantity = sci.Quantity,
                    StockQuantity = product.StockQuantity,
                    //TODO: where does AttributeInfo come from and how is it used
                    //AttributeInfo = _productAttributeFormatter.FormatAttributes(sci.Product, sci.AttributesXml),
                    LotBidEntry = _lotService.GetLotBidEntryModel(product.Id)
                };

                //NJM: count lots as separate from products so can determine if need to show product wishlist and lot wishlist in view
                if (bidItemModel.LotBidEntry.ProductIsLot)
                {
                    model.TotalLots += 1;
                }

                //TODO: fill in the lot bid entry model in the shopping cart only if auction site

                //allowed quantities
                //NJM: do not use allowed quantities for biddable lots. StockQuantity will be used for "dup lots" 
                //(not grouped products which is used for variants)
                //var allowedQuantities = sci.Product.ParseAllowedQuantities();
                //foreach (var qty in allowedQuantities)
                //{
                //    cartItemModel.AllowedQuantities.Add(new SelectListItem
                //    {
                //        Text = qty.ToString(),
                //        Value = qty.ToString(),
                //        Selected = sci.Quantity == qty
                //    });
                //}


                //recurring info
                //NJM: do not use recurring info for biddable lots. 
                //if (sci.Product.IsRecurring)
                //    cartItemModel.RecurringInfo = string.Format(_localizationService.GetResource("ShoppingCart.RecurringPeriod"), sci.Product.RecurringCycleLength, sci.Product.RecurringCyclePeriod.GetLocalizedEnum(_localizationService, _workContext));

                //rental info
                //NJM: do not use rental info for biddable lots. 
                //if (sci.Product.IsRental)
                //{
                //    var rentalStartDate = sci.RentalStartDateUtc.HasValue ? sci.Product.FormatRentalDate(sci.RentalStartDateUtc.Value) : "";
                //    var rentalEndDate = sci.RentalEndDateUtc.HasValue ? sci.Product.FormatRentalDate(sci.RentalEndDateUtc.Value) : "";
                //    cartItemModel.RentalInfo = string.Format(_localizationService.GetResource("ShoppingCart.Rental.FormattedDate"),
                //        rentalStartDate, rentalEndDate);
                //}

                //unit prices
                //TODO: check use of callforprice for unsolds
                //if (product.CallForPrice)
                //{
                //    cartItemModel.UnitPrice = _localizationService.GetResource("Products.CallForPrice");
                //}
                //else
                //{
                //    decimal taxRate;
                //    decimal shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetUnitPrice(sci), out taxRate);
                //    decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency);
                //    cartItemModel.UnitPrice = _priceFormatter.FormatPrice(shoppingCartUnitPriceWithDiscount);
                //}

                //subtotal, discount
                //NJM: subtotal, discount not currently used for lots
                //TODO: check use of subtotal, discount for lots
                //if (sci.Product.CallForPrice)
                //{
                //    cartItemModel.SubTotal = _localizationService.GetResource("Products.CallForPrice");
                //}
                //else
                //{
                //    //sub total
                //    Discount scDiscount;
                //    decimal shoppingCartItemDiscountBase;
                //    decimal taxRate;
                //    decimal shoppingCartItemSubTotalWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetSubTotal(sci, true, out shoppingCartItemDiscountBase, out scDiscount), out taxRate);
                //    decimal shoppingCartItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency);
                //    cartItemModel.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount);

                //    //display an applied discount amount
                //    if (scDiscount != null)
                //    {
                //        shoppingCartItemDiscountBase = _taxService.GetProductPrice(sci.Product, shoppingCartItemDiscountBase, out taxRate);
                //        if (shoppingCartItemDiscountBase > decimal.Zero)
                //        {
                //            decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency);
                //            cartItemModel.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount);
                //        }
                //    }
                //}

                //picture
                if (_shoppingCartSettings.ShowProductImagesOnShoppingCart)
                {
                    bidItemModel.Picture = PrepareMyBidPictureModel(bidItemModel,
                        _mediaSettings.CartThumbPictureSize, true, bidItemModel.ProductName); //TODO: clean up this signature
                }

                //item warnings
                //var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings(
                //    _workContext.CurrentCustomer,
                //    sci.ShoppingCartType,
                //    sci.Product,
                //    sci.StoreId,
                //    sci.AttributesXml,
                //    sci.CustomerEnteredPrice,
                //    sci.RentalStartDateUtc,
                //    sci.RentalEndDateUtc,
                //    sci.Quantity,
                //    false);

                var itemWarnings = new List<string>();
                foreach (var warning in itemWarnings)
                    bidItemModel.Warnings.Add(warning);

                model.Lots.Add(bidItemModel);
            }
        }
        protected virtual PictureModel PrepareMyBidPictureModel(AUMyBidsModel.MyBidItemItemModel bidItemModel,
            int pictureSize, bool showDefaultPicture, string productName)
        {
            //var pictureCacheKey = string.Format(ModelCacheEventConsumer.CART_PICTURE_MODEL_KEY, sci.Id, pictureSize, true, _workContext.WorkingLanguage.Id, _webHelper.IsCurrentConnectionSecured(), _storeContext.CurrentStore.Id);
            //var model = _cacheManager.Get(pictureCacheKey,
            //    //as we cache per user (shopping cart item identifier)
            //    //let's cache just for 3 minutes
            //    3, () =>
            //    {
                    //NJM: mybids picture hacks shopping cart item picture
                    //var sciPicture = sci.Product.GetProductPicture(sci.AttributesXml, _pictureService, _productAttributeParser);
                    var defaultProductPicture = _pictureService.GetPicturesByProductId(bidItemModel.ProductId, 1).FirstOrDefault();
                    string pictureThumbnailUrl = _pictureService.GetPictureUrl(defaultProductPicture, 75, true);

                    return new PictureModel
                    {
                        //ImageUrl = _pictureService.GetPictureUrl(sciPicture, pictureSize, showDefaultPicture),
                        ImageUrl = pictureThumbnailUrl,
                        Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), productName),
                        AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), productName),
                    };
                //});
            //return model;
        }