private int SyncOrders(ConnectsterUser user)
        {
            int returnCount = 0;

            //Ask the db for credentials
            ShopifyStoreAuth shopifyAuth = _database.SelectShopifyUserDetails(user);
            ShopsterUser shopsterUser = _database.SelectShopsterUserDetails(user);

            var apiContext = new ConnectsterApiContext
                                 {
                                     AccessToken = shopsterUser.AuthToken,
                                     AccessTokenSecret = shopsterUser.AuthSecret
                                 };

            List<ShopifyOrder> shopifyOrders = _shopifyComm.GetListAllOrders(shopifyAuth);

            //Think of this dictionary as Dictionary<ShopifyOrderId, ShopsterOrderId>
            Dictionary<int, int> shopsterifyOrderMap = _database.SelectOrderMappingsForUser(user);
            List<ConnectsterProduct> productMappingsList = _database.SelectProductForUser(user);
            var productDictionary = new Dictionary<int, int>(productMappingsList.Count);
            foreach (ConnectsterProduct item in productMappingsList)
            {
                productDictionary.Add(item.SourceId, item.DestinationId);
            }

            if (shopsterifyOrderMap == null || shopifyOrders == null)
            {
                //Todo Logging and fail
                return 0;
            }

            foreach (ShopifyOrder shopifyOrder in shopifyOrders)
            {
                if (shopsterifyOrderMap.Keys.Contains(shopifyOrder.Id))
                {
                    continue; //Skip this order, it already has been processed by shopsterify
                }

                int? newOrder;
                if ((newOrder = _shopsterComm.PlaceOrder(apiContext, shopifyOrder, productDictionary)) != null)
                {
                    returnCount++;
                    if (_database.CreateOrderMapping(user, shopifyOrder, (int) newOrder))
                    {
                    }
                }
            }

            return returnCount;
        }
        private int SyncProducts(ConnectsterUser user)
        {
            int returnCount = 0;

            //Ask the db for credentials
            ShopifyStoreAuth shopifyAuth = _database.SelectShopifyUserDetails(user);
            ShopsterUser shopsterUser = _database.SelectShopsterUserDetails(user);

            var apiContext = new ConnectsterApiContext
                                 {
                                     AccessToken = shopsterUser.AuthToken,
                                     AccessTokenSecret = shopsterUser.AuthSecret
                                 };

            List<InventoryItemType> shopsterList;
            ConnectsterProductMap productMap;
            List<ShopifyProduct> shopifyItems;
            ShopifyMetafieldMap shopifyMapping;

            //Todo: Decide the lowest DetailGroup needed
            try
            {
                shopsterList =
                    _shopsterComm.GetAllInventoryItemsForUser(apiContext, "All").Where(
                        item => item.IsStoreVisible == true).Select(item => item).ToList();
                productMap = new ConnectsterProductMap(user);
                shopifyItems = _shopifyComm.GetAllProducts(shopifyAuth);
                shopifyMapping = new ShopifyMetafieldMap(_shopifyComm, shopifyAuth);
            }
            catch (Exception e)
            {
                logger.FatalFormat(
                    "ConnectsterController::SyncProducts(): Exception while creating lists. Exception is ({0}).",
                    e.Message);
                return 0;
                //todo : throw our own exception class to the program to indicate the user should be disabled or ignored for a while.
            }

            if (shopifyItems == null)
            {
                //todo : again we need to throw our own exception class to indicate the user should be disabled or ignored for a while.
                return 0;
            }

            //create these lists here to reduce redundancy in proceeding calls.
            List<int> shopsterIds = shopsterList.Select(item => Convert.ToInt32(item.ItemId)).ToList();
            List<int> shopifyIds = shopifyItems.Select(item => (int) item.Id).ToList();
            _database.UpdateShopsterProductTimeStamps(shopsterList, DateTime.UtcNow);

            #if DEBUG
            //Some debugging info
            foreach (ConnectsterProduct mappedItem in productMap.GetMappedItems())
            {
                logger.DebugFormat(
                    "ConnectsterController::CreateListsAndBegin(): ShopsterifyDB has ShopsterId({0}, Date({1:yyyy-MM-dd HH:mm:ss}) \tMapped to \t ShopifyId({2}, Date({3:yyyy-MM-dd HH:mm:ss})",
                    mappedItem.SourceId, mappedItem.SourceDate, mappedItem.DestinationId, mappedItem.DestinationDate);
            }

            foreach (ShopifyProduct item in shopifyItems)
            {
                logger.DebugFormat(
                    "ConnectsterController::CreateListsAndBegin(): Shopify has shopifyItem({0}, Date:{1: yyyy-MM-dd HH:mm:ss})",
                    item.Id, ((DateTime) item.Variants[0].UpdatedAt));
            }

            foreach (ShopifyMetafieldMapping mapping in shopifyMapping.GetMappedItems())
            {
                logger.DebugFormat("Shopify has Item({0}) --> ShopsterId({1})", mapping.SourceId, mapping.DestinationId);
            }
            #endif

            //Now do the actual syncronizing actions

            //This will ensure that all shopster products are in the db and on shopify
            returnCount += PushProductToShopify(shopsterList, productMap, shopifyMapping, shopifyIds, shopifyItems,
                                                shopifyAuth, apiContext);

            //This will clean up all the broken Maps
            returnCount += FixOrphanedMappings(shopsterIds, productMap, shopifyMapping, shopifyIds, shopifyAuth);

            //This will delete all orphaned shopify items (not mapped at all, but tagged as shopster items).
            return (returnCount +
                    DeleteOrphanedShopifyProducts(shopsterList, productMap, shopifyMapping, shopifyAuth));
        }
        public List<InventoryItemType> GetAllInventoryItemsForUser(ConnectsterApiContext apiContext, string group)
        {
            if (apiContext == null)
            {
                throw new ArgumentException("apiContext may not be null");
            }


            switch (group)
            {
                case "Group1":
                case "Group2":
                case "Group3":
                case "Group4":
                case "Group5":
                case "All":
                    break;
                default:
                    group = "All"; //Just default, no need to fail. 
                    break;
            }


            const int pageSize = 50;
            var returnList = new Dictionary<int, InventoryItemType>();

            try
            {
                int pageNum = 0; //to keep our current page number

                var call = new GetInventoryItemsCall(apiContext) {Request = new GetInventoryItemsRequestType()};

                do
                {
                    call.Request.PageIndex = pageNum++;
                    call.Request.PageSize = pageSize;
                    call.Request.DetailGroups = group;
                    call.Execute();

                    if (call.Response.Status == ResponseStatusType.Failed)
                    {
                        // Not sure what to do
                        ApiLogger.DebugFormat(
                            "ShopsterCommunicator::GetAllInventoryItemsForUser(): call.Response.Status == Failed. PageNum({0}), PageSize({1}), Group({2})",
                            pageNum, pageSize, group);
                        return null;
                            //return null to indcate error, otherwise shopsterify will think a bunch of items have been deleted.
                    }

                    //TODO : handle warnings from shopsterAPI
                    if (call.Response.Status == ResponseStatusType.Success ||
                        call.Response.Status == ResponseStatusType.SuccessWithWarnings)
                    {
                        foreach (InventoryItemType item in call.Response.Items)
                        {
                            returnList.Add(Convert.ToInt32(item.ItemId), item);
                        }
                        if (call.Response.Status == ResponseStatusType.SuccessWithWarnings)
                        {
                            int i = 0;
                            foreach (var error in call.Response.Errors)
                            {
                                ApiLogger.WarnFormat(
                                    "ShopsterCommunicator::GetAllInventoryItemsForUser(): Warning/Error[{0}] for user({1}) : {2}",
                                    i, apiContext.AccessToken, error.Message);
                                i++;
                            }
                        }
                    }

                    //Repeat the call until we have enough items (==call.Response.NumFound) or we've gone through enough pages. 
                } while (
                    !(returnList.Count >= call.Response.NumFound || pageNum > ((call.Response.NumFound/pageSize) + 1)));

                return returnList.Count > 0 ? returnList.Values.ToList() : new List<InventoryItemType>(1);
                    //Return the list
            }
            catch (ApiException ae)
            {
                string result = ae.Message;


                if (ae is ApiFaultException)
                {
                    var afe = (ApiFaultException) ae;
                    result = string.Format("({0}) {1}: {2}", afe.Error.SeverityCode, result,
                                           afe.Error.Message);
                    ApiLogger.DebugFormat(
                        "ShopsterCommunicator::GetAllInventoryItemsForUser(): ApiFaultException: ({0}) {1}: {2}",
                        afe.Error.SeverityCode, result,
                        afe.Error.Message);
                }
                return null;
            }
            //Return in either try or catch.		
        }