public static long GetRemainingCredits(this DataCache dataCache, string account, long cost, long initialCredits,
            TimeSpan timeout, ICostCalculator costCalculator)
        {
            if (string.IsNullOrWhiteSpace(account))
            {
                throw new ArgumentNullException("account");
            }
            if (cost <= 0)
            {
                throw new ArgumentOutOfRangeException("cost", "Cost cannot be negative");
            }
            if (initialCredits <= 0)
            {
                throw new ArgumentOutOfRangeException("initialCredits", "Initial credit cannot be negative");
            }
            if (timeout.TotalMilliseconds <= 0)
            {
                throw new ArgumentOutOfRangeException("timeout", "Timeout must be a time interval");
            }

            DataCacheItem cacheItem = dataCache.GetCacheItem(account);


            long remainingCredits;

            if (cacheItem == null)
            {
                remainingCredits = costCalculator.CalculateRemainingCredits(initialCredits, cost);

                if (remainingCredits <= 0)
                {
                    return remainingCredits;
                }

                dataCache.Add(account, remainingCredits, timeout);

                return remainingCredits;
            }

            if (!(cacheItem.Value is long))
            {
                throw new InvalidOperationException(string.Format("The cached value with key {0} is not a valid long",
                    account));
            }

            var cachedValue = (long) cacheItem.Value;

            if (cachedValue <= 0)
            {
                return -1;
            }

            remainingCredits = costCalculator.CalculateRemainingCredits(cachedValue, cost);
            
            var newTimeout = cacheItem.Timeout;

            dataCache.Put(account, remainingCredits, cacheItem.Version, newTimeout);

            return remainingCredits;
        }