public ItemInstance(ItemInstanceJson json, GameSchema reference)
        {
            InstanceID = json.id;
            OriginalInstanceID = json.original_id;
            Item = reference.GetItem(json.defindex);
            Level = json.level;
            Count = json.quantity;
            Tradable = !json.flag_cannot_trade;
            Craftable = !json.flag_cannot_craft;
            Quality = (Quality)json.quality;
            CustomName = json.custom_name;
            CustomDescription = json.custom_desc;
            Style = json.style;

            InventoryLocationFlags flags = (InventoryLocationFlags)json.inventory;
            BackpackSlot = flags.GetBackpackPos();
            IsNewToBackpack = flags.IsNewItem();

            Attributes = new List<AppliedInstanceAttribute>();
            if (json.attributes != null)
            {
                foreach (AppliedItemInstanceAttributeJson aiiaj in json.attributes)
                {
                    Attributes.Add(new AppliedInstanceAttribute(aiiaj));
                }
            }

            if (json.contained_item != null)
            {
                WrappedItem = new ItemInstance(json.contained_item, reference);
            }
        }
        public bool SetItemFromFullSlot(ItemInstance inst)
        {
            if (!inst.BackpackSlot.IsBetween(MinSlotID, MaxSlotID))
            {
                return false;
            }

            int index = inst.BackpackSlot - MinSlotID;
            Items[index] = inst;
            return true;
        }
        public BackpackPage(List<ItemInstance> items, int pageid)
        {
            PageID = pageid;

            Items = new ItemInstance[50];

            foreach (ItemInstance i in items)
            {
                if ((i.BackpackSlot - 1).IsBetween(MinSlotID, MaxSlotID) && !i.IsNewToBackpack)
                {
                    Items[i.BackpackSlot - MinSlotID - 1] = i;
                }
            }
        }
        public ItemPriceInfo(ItemInstance inst)
        {
            Item = inst.Item;
            Quality = inst.Quality;
            Killstreak = inst.GetKillstreak();
            Unusual = inst.GetUnusual();
            CrateSeries = inst.GetCrateSeries();
            _skin = Item.GetSkin();
            SkinWear = inst.GetSkinWear();

            Craftable = inst.Craftable;
            Tradable = inst.Tradable;
            Australium = inst.IsAustralium();
        }
        public ClassifiedsListing(ItemInstance inst, Price price, string steamID, string nickname,
			string url, string comment = "", bool buyoutOnly = true, OrderType order = OrderType.Sell)
        {
            ItemInstance = inst;
            Price = price;
            ListerSteamID64 = steamID;
            if (nickname != null)
            {
                ListerNickname = WebUtility.HtmlDecode(nickname);
            }

            BuyoutOnly = buyoutOnly;

            if (!comment.IsNullOrWhitespace())
            {
                Comment = WebUtility.HtmlDecode(comment);
            }

            OrderType = order;
            OfferURL = url;
        }
        public static List<ClassifiedsListing> GetClassifieds(Item item, Quality quality,
			bool craftable = true, bool tradable = true, bool australium = false)
        {
            string url = MakeBpTfClassifiedsUrl(item, quality, craftable, tradable, australium);

            VersatileIO.Verbose("Downloading listings from {0}...", url.Shorten(100, ""));
            WebClient client = new WebClient { Encoding = Encoding.UTF8 };
            string html = client.DownloadString(url);
            //Logger.Log("  Download complete.", ConsoleColor.DarkGray);

            VersatileIO.Verbose("  Scraping listings from HTML...");
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html);

            List<ClassifiedsListing> results = new List<ClassifiedsListing>();

            HtmlNode root = doc.DocumentNode;

            #region sells
            HtmlNode sellOrderRoot = root.Descendants("ul").FirstOrDefault(n => n.Attributes.Contains("class") &&
                n.Attributes["class"].Value == "media-list");

            if (sellOrderRoot == null)
            {
                VersatileIO.Verbose("  No sell orders found.");
            }
            else
            {
                List<HtmlNode> sellOrderBases = sellOrderRoot.Descendants("li").ToList();

                foreach (HtmlNode sob in sellOrderBases)
                {
                    HtmlNode sellData = sob.Descendants("li").FirstOrDefault();

                    if (sellData == null)
                    {
                        continue;
                    }

                    Item foundItem = item;

                    string sellItemName = sellData.Attributes["data-name"].Value; // not really necessary
                    string sellTradable = sellData.Attributes["data-tradable"]?.Value; // or this
                    string sellCraftable = sellData.Attributes["data-craftable"]?.Value; // or this
                    string sellQuality = sellData.Attributes["data-quality"].Value; // or even this
                    string sellComment = sellData.Attributes["data-listing_comment"]?.Value;
                    string sellPrice = sellData.Attributes["data-listing_price"].Value;
                    string sellLevel = sellData.Attributes["data-level"]?.Value ?? "-1";
                    string sellID = sellData.Attributes["data-id"].Value;
                    string sellerSteamID64 = sellData.Attributes["data-listing_account_id"].Value;
                    string sellerNickname = sellData.Attributes["data-listing_name"]?.Value;
                    string sellOfferUrl = sellData.Attributes["data-listing_offers_url"]?.Value;
                    string sellOriginalID = sellData.Attributes["data-original_id"]?.Value;
                    string sellCustomName = sellData.Attributes["data-custom_name"]?.Value;
                    string sellCustomDesc = sellData.Attributes["data-custom_desc"]?.Value;
                    string sellBuyoutOnly = sellData.Attributes["data-listing_buyout"]?.Value ?? "0";
                    string sellMarketName = sellData.Attributes["data-market-name"]?.Value;

                    if (sellMarketName != null)
                    {
                        MarketPricing mp = DataManager.MarketPrices.GetPricing(sellMarketName);
                        if (mp?.GunMettleSkin != null)
                        {
                            foundItem = mp.GunMettleSkin.GetItemForm(DataManager.Schema);
                        }
                    }

                    ulong id = ulong.Parse(sellID); // really funky syntax down here -v
                    ulong? originalID = sellOriginalID != null ? new ulong?(ulong.Parse(sellOriginalID)) : null;
                    Price price = Price.ParseFancy(sellPrice);
                    int level = int.Parse(sellLevel);
                    bool buyoutOnly = BooleanUtil.ParseLoose(sellBuyoutOnly);

                    ItemInstance instance = new ItemInstance(foundItem, id, level, quality, craftable,
                        sellCustomName, sellCustomDesc, originalID, tradable);
                    ClassifiedsListing listing = new ClassifiedsListing(instance, price, sellerSteamID64,
                        sellerNickname, sellOfferUrl, sellComment, buyoutOnly, OrderType.Sell);

                    if (string.IsNullOrWhiteSpace(listing.OfferURL))
                    {
                        continue;
                    }

                    results.Add(listing);
                }
                VersatileIO.Verbose("  Sell order scrape complete.");
            }
            #endregion sells

            #region buys
            HtmlNode buyOrderRoot = root.Descendants("ul").LastOrDefault(n => n.Attributes.Contains("class") &&
                n.Attributes["class"].Value == "media-list");

            if (buyOrderRoot == null)
            {
                VersatileIO.Verbose("  No buy orders found.");
            }
            else
            {
                List<HtmlNode> buyOrderBases = buyOrderRoot.Descendants("li").ToList();

                foreach (HtmlNode bob in buyOrderBases)
                {
                    HtmlNode buyData = bob.Descendants("li").FirstOrDefault();

                    if (buyData == null)
                    {
                        continue;
                    }

                    Item foundItem = item;

                    string buyItemName = buyData.Attributes["data-name"].Value; // not really necessary
                    string buyTradable = buyData.Attributes["data-tradable"]?.Value; // or this
                    string buyCraftable = buyData.Attributes["data-craftable"]?.Value; // or this
                    string buyQuality = buyData.Attributes["data-quality"].Value; // or even this
                    string buyComment = buyData.Attributes["data-listing_comment"]?.Value;
                    string buyPrice = buyData.Attributes["data-listing_price"].Value;
                    string buyLevel = buyData.Attributes["data-level"]?.Value ?? "-1";
                    string buyID = buyData.Attributes["data-id"]?.Value ?? "0";
                    string buyerSteamID64 = buyData.Attributes["data-listing_account_id"].Value;
                    string buyerSteamNickname = buyData.Attributes["data-listing_name"]?.Value;
                    string buyOfferUrl = buyData.Attributes["data-listing_offers_url"]?.Value;
                    string buyOriginalID = buyData.Attributes["data-original_id"]?.Value;
                    string buyCustomName = buyData.Attributes["data-custom_name"]?.Value;
                    string buyCustomDesc = buyData.Attributes["data-custom_desc"]?.Value;
                    string buyBuyoutOnly = buyData.Attributes["data-listing_buyout"]?.Value ?? "0";
                    string buyMarketName = buyData.Attributes["data-market-name"]?.Value;

                    if (buyMarketName != null)
                    {
                        MarketPricing mp = DataManager.MarketPrices.GetPricing(buyMarketName);
                        if (mp != null && mp.GunMettleSkin != null)
                        {
                            foundItem = mp.GunMettleSkin.GetItemForm(DataManager.Schema);
                        }
                    }

                    ulong id = ulong.Parse(buyID == "" ? "0" : buyID); // really funky syntax down here -v
                    ulong? originalID = buyOriginalID != null ? new ulong?(ulong.Parse(buyOriginalID == "" ? "0" : buyOriginalID)) : null;
                    Price price = Price.ParseFancy(buyPrice);
                    int level = int.Parse(buyLevel);
                    bool buyoutOnly = BooleanUtil.ParseLoose(buyBuyoutOnly);

                    ItemInstance instance = new ItemInstance(foundItem, id, level, quality, craftable,
                        buyCustomName, buyCustomDesc, originalID, tradable);
                    ClassifiedsListing listing = new ClassifiedsListing(instance, price, buyerSteamID64, buyerSteamNickname,
                        buyOfferUrl, buyComment, buyoutOnly, OrderType.Buy);

                    if (string.IsNullOrWhiteSpace(listing.OfferURL))
                    {
                        continue;
                    }

                    results.Add(listing);
                }

                VersatileIO.Verbose("  Buy order scrape complete.");
            }
            #endregion buys

            return results;
        }
        public bool MatchesInstance(ItemInstance inst)
        {
            if (inst.Item != Item)
            {
                return false;
            }

            if (inst.GetKillstreak() != Killstreak)
            {
                return false;
            }

            if (inst.Quality != Quality)
            {
                return false;
            }

            return true;
        }
 public bool SetItemFromFullSlot(ushort slot, ItemInstance inst)
 {
     inst.BackpackSlot = slot;
     return SetItemFromFullSlot(inst);
 }
 /// <summary>
 /// Gets the resulting price from complex algorithm.
 /// </summary>
 /// <param name="inst">Item to check</param>
 /// <returns>The resulting price</returns>
 public static PriceRange? GetPrice(ItemInstance inst)
 {
     return GetPrice(new ItemPriceInfo(inst));
 }
 /// <summary>
 /// Gets the resulting price from complex algorithm, with the flag "market" if the price
 /// was obtained from the Steam Community Market.
 /// </summary>
 /// <param name="inst">Item to check</param>
 /// <returns>The resulting price with flags</returns>
 public static FlaggedResult<PriceRange?, string> GetPriceFlagged(ItemInstance inst)
 {
     return GetPriceFlagged(new ItemPriceInfo(inst));
 }