/// <summary>
        /// Gets a random file name that matches the crop growth image at the given position
        /// Will remove the name found from the list
        /// </summary>
        /// <param name="position">The position</param>
        /// <returns>The selected file name</returns>
        protected override string GetRandomFileName(Point position)
        {
            string fileName = "";

            int  cropId = CropGrowthImagePointsToIds[position];
            Item item   = ItemList.Items[cropId];

            SeedItem seedItem = item.Id == (int)ObjectIndexes.CoffeeBean ?
                                (SeedItem)item : ((CropItem)item).MatchingSeedItem;
            CropGrowthInformation growthInfo = seedItem.CropGrowthInfo;

            FixWidthValue(seedItem.CropGrowthInfo.GraphicId);

            if (item.IsFlower)
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(FlowerImages);

                if (!seedItem.CropGrowthInfo.TintColorInfo.HasTint)
                {
                    fileName = $"{fileName.Substring(0, fileName.Length - 4)}-NoHue.png";
                }
            }

            else if (growthInfo.IsTrellisCrop)
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(TrellisImages);
            }

            else if (growthInfo.RegrowsAfterHarvest)
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(RegrowingImages);
            }

            else
            {
                fileName = Globals.RNGGetAndRemoveRandomValueFromList(NormalImages);

                if (growthInfo.GrowthStages.Count <= 4)
                {
                    fileName += "-4.png";
                }

                else
                {
                    fileName += "-5.png";
                }
            }

            if (string.IsNullOrEmpty(fileName) || fileName == "-4.png" || fileName == "-5.png")
            {
                Globals.ConsoleWarn($"Using default image for crop growth - you may not have enough crop growth images: {position.X}, {position.Y}");
                return(null);
            }


            CropIdsToImageNames[cropId] = Path.GetFileName(fileName).Replace("-4.png", ".png").Replace("-5.png", ".png").Replace("-NoHue.png", ".png");
            return(fileName);
        }
        /// <summary>
        /// Randomizes the crops - currently only does prices, and only for seasonal crops
        /// </summary>
        /// <param name="editedObjectInfo">The edited object information</param>
        /// crop format: name/price/-300/Seeds -74/name/tooltip
        private static void RandomizeCrops(EditedObjectInformation editedObjectInfo)
        {
            List <int> regrowableSeedIdsToRandomize = ItemList.GetSeeds().Cast <SeedItem>()
                                                      .Where(x => x.Randomize && x.CropGrowthInfo.RegrowsAfterHarvest)
                                                      .Select(x => x.Id)
                                                      .ToList();
            List <int> regrowableSeedIdsToRandomizeCopy = new List <int>(regrowableSeedIdsToRandomize);

            List <int> nonRegrowableSeedIdsToRandomize = ItemList.GetSeeds().Cast <SeedItem>()
                                                         .Where(x => x.Randomize && !x.CropGrowthInfo.RegrowsAfterHarvest)
                                                         .Select(x => x.Id)
                                                         .ToList();
            List <int> nonRegrowableSeedIdsToRandomizeCopy = new List <int>(nonRegrowableSeedIdsToRandomize);

            // Fill up a dictionary to remap the seed values
            Dictionary <int, int> seedMappings = new Dictionary <int, int>();           // Original value, new value

            foreach (int originalRegrowableSeedId in regrowableSeedIdsToRandomize)
            {
                seedMappings.Add(originalRegrowableSeedId, Globals.RNGGetAndRemoveRandomValueFromList(regrowableSeedIdsToRandomizeCopy));
            }

            foreach (int originalNonRegrowableSeedId in nonRegrowableSeedIdsToRandomize)
            {
                seedMappings.Add(originalNonRegrowableSeedId, Globals.RNGGetAndRemoveRandomValueFromList(nonRegrowableSeedIdsToRandomizeCopy));
            }

            // Loop through the dictionary and reassign the values, keeping the seasons the same as before
            foreach (KeyValuePair <int, int> seedMapping in seedMappings)
            {
                int originalValue = seedMapping.Key;
                int newValue      = seedMapping.Value;

                CropGrowthInformation cropInfoToAdd = CropGrowthInformation.ParseString(CropGrowthInformation.DefaultStringData[newValue]);
                cropInfoToAdd.GrowingSeasons = CropGrowthInformation.ParseString(CropGrowthInformation.DefaultStringData[originalValue]).GrowingSeasons;
                cropInfoToAdd.GrowthStages   = GetRandomGrowthStages(cropInfoToAdd.GrowthStages.Count);
                cropInfoToAdd.CanScythe      = Globals.RNGGetNextBoolean(10);
                cropInfoToAdd.DaysToRegrow   = cropInfoToAdd.RegrowsAfterHarvest ? Range.GetRandomValue(1, 7) : -1;

                if (!Globals.Config.RandomizeCrops)
                {
                    continue;
                }                                                                 // Preserve the original seasons/etc
                CropGrowthInformation.CropIdsToInfo[originalValue] = cropInfoToAdd;
            }

            // Set the object info
            List <CropItem> randomizedCrops = ItemList.GetCrops(true).Cast <CropItem>()
                                              .Where(x => nonRegrowableSeedIdsToRandomize.Union(regrowableSeedIdsToRandomize).Contains(x.MatchingSeedItem.Id))
                                              .ToList();
            List <CropItem> vegetables = randomizedCrops.Where(x => !x.IsFlower).ToList();
            List <CropItem> flowers    = randomizedCrops.Where(x => x.IsFlower).ToList();

            List <string> vegetableNames   = NameAndDescriptionRandomizer.GenerateVegetableNames(vegetables.Count + 1);
            List <string> cropDescriptions = NameAndDescriptionRandomizer.GenerateCropDescriptions(randomizedCrops.Count);

            SetCropAndSeedInformation(
                editedObjectInfo,
                vegetables,
                vegetableNames,
                cropDescriptions);                 // Note: It removes the descriptions it uses from the list after assigning them- may want to edit later

            SetUpCoffee(editedObjectInfo, vegetableNames[vegetableNames.Count - 1]);
            SetUpRice(editedObjectInfo);

            SetCropAndSeedInformation(
                editedObjectInfo,
                flowers,
                NameAndDescriptionRandomizer.GenerateFlowerNames(flowers.Count),
                cropDescriptions);                 // Note: It removes the descriptions it uses from the list after assigning them- may want to edit later

            SetUpCookedFood(editedObjectInfo);
        }
        /// <summary>
        /// Calculates the seed price based on the seed growth info and price
        /// </summary>
        /// <param name="seed">The seed</param>
        /// <returns>
        /// Returns a value based on a random multiplier, regrowth days, and
        /// potential amount per harvest
        /// </returns>
        private static int CalculateCropPrice(SeedItem seed)
        {
            int seedPrice = seed.Price * 2;             // The amount we store here is half of what we want to base this off of
            CropGrowthInformation growthInfo = seed.CropGrowthInfo;

            double multiplier = 1;

            if (seedPrice < 31)
            {
                multiplier = Range.GetRandomValue(15, 40) / (double)10;
            }
            else if (seedPrice < 61)
            {
                multiplier = Range.GetRandomValue(15, 35) / (double)10;
            }
            else if (seedPrice < 91)
            {
                multiplier = Range.GetRandomValue(15, 30) / (double)10;
            }
            else if (seedPrice < 121)
            {
                multiplier = Range.GetRandomValue(15, 25) / (double)10;
            }
            else
            {
                multiplier = Range.GetRandomValue(15, 20) / (double)10;
            }

            double regrowthDaysMultiplier = 1;

            switch (growthInfo.DaysToRegrow)
            {
            case 1: regrowthDaysMultiplier = 0.3; break;

            case 2: regrowthDaysMultiplier = 0.4; break;

            case 3: regrowthDaysMultiplier = 0.5; break;

            case 4: regrowthDaysMultiplier = 0.6; break;

            case 5: regrowthDaysMultiplier = 0.7; break;

            case 6: regrowthDaysMultiplier = 0.8; break;

            case 7: regrowthDaysMultiplier = 0.9; break;

            default: regrowthDaysMultiplier = 1; break;
            }

            double amountPerHarvestMultiplier = 1;

            switch (growthInfo.ExtraCropInfo.MinExtra)
            {
            case 0: break;

            case 1: break;

            case 2: amountPerHarvestMultiplier = 0.6; break;

            case 3: amountPerHarvestMultiplier = 0.45; break;

            case 4: amountPerHarvestMultiplier = 0.3; break;

            default:
                Globals.ConsoleError($"Unexpected seed with more than 4 minimum extra crops: {seed.Id}");
                break;
            }
            if (growthInfo.ExtraCropInfo.CanGetExtraCrops && amountPerHarvestMultiplier == 1)
            {
                amountPerHarvestMultiplier = 0.9;
            }

            return((int)(seedPrice * multiplier * regrowthDaysMultiplier * amountPerHarvestMultiplier));
        }
        /// <summary>
        /// Parses a string from the Crops data file into a CropGrowthInformation object
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static CropGrowthInformation ParseString(string input)
        {
            CropGrowthInformation cropGrowthInfo = new CropGrowthInformation();
            int result;

            string[] fields = input.Split('/');
            if (fields.Length != 9)
            {
                Globals.ConsoleError($"Invalid string passed when parsing crop info: {input}");
                return(null);
            }

            // Growth stages
            string[] growthStages = fields[(int)CropGrowthFields.GrowthStages].Split(' ');
            foreach (string growthStage in growthStages)
            {
                if (int.TryParse(growthStage, out result))
                {
                    cropGrowthInfo.GrowthStages.Add(result);
                }
                else
                {
                    Globals.ConsoleError($"Tried to parse {growthStage} into a growth stage when parsing: {input}");
                    return(null);
                }
            }

            // Seasons
            string[] seasonStrings = fields[(int)CropGrowthFields.Seasons].Split(' ');
            foreach (string seasonString in seasonStrings)
            {
                switch (seasonString.ToLower())
                {
                case "spring":
                    cropGrowthInfo.GrowingSeasons.Add(Seasons.Spring);
                    break;

                case "summer":
                    cropGrowthInfo.GrowingSeasons.Add(Seasons.Summer);
                    break;

                case "fall":
                    cropGrowthInfo.GrowingSeasons.Add(Seasons.Fall);
                    break;

                case "winter":
                    cropGrowthInfo.GrowingSeasons.Add(Seasons.Winter);
                    break;

                default:
                    Globals.ConsoleError($"Tries to parse {seasonString} into a season when parsing: {input}");
                    return(null);
                }
            }

            // Graphic id
            string graphicId = fields[(int)CropGrowthFields.GraphicId];

            if (int.TryParse(graphicId, out result))
            {
                cropGrowthInfo.GraphicId = result;
            }
            else
            {
                Globals.ConsoleError($"Tried to parse {result} into a graphic id when parsing: {input}");
                return(null);
            }

            // Crop Id
            string cropId = fields[(int)CropGrowthFields.CropId];

            if (int.TryParse(cropId, out result))
            {
                cropGrowthInfo.CropId = result;
            }
            else
            {
                Globals.ConsoleError($"Tried to parse {result} into a crop id when parsing: {input}");
                return(null);
            }

            // Amount per harvest
            string daysToRegrow = fields[(int)CropGrowthFields.DaysToRegrow];

            if (int.TryParse(daysToRegrow, out result))
            {
                cropGrowthInfo.DaysToRegrow = result;
            }
            else
            {
                Globals.ConsoleError($"Tried to parse {result} into the amount per harvest when parsing: {input}");
                return(null);
            }

            // Can scythe
            string canScythe = fields[(int)CropGrowthFields.CanScythe];

            if (int.TryParse(canScythe, out result))
            {
                cropGrowthInfo.CanScythe = result == 1;
            }
            else
            {
                Globals.ConsoleError($"Tried to parse {result} into the CanScythe flag id when parsing: {input}");
                return(null);
            }

            // Extra crop info
            string extraCropInfoString = fields[(int)CropGrowthFields.ExtraCropInfo];

            cropGrowthInfo.ExtraCropInfo = ExtraCropInformation.ParseString(extraCropInfoString);
            if (cropGrowthInfo.ExtraCropInfo == null)
            {
                return(null);
            }

            // Is trellis crop
            string isTrellisCropString = fields[(int)CropGrowthFields.IsTrellisCrop];

            if (bool.TryParse(isTrellisCropString, out bool boolResult))
            {
                cropGrowthInfo.IsTrellisCrop = boolResult;
            }
            else
            {
                Globals.ConsoleError($"Tried to parse {isTrellisCropString} into the isTrellisCrop boolean when parsing: {input}");
                return(null);
            }

            // Tint color info
            string tintColorInfoString = fields[(int)CropGrowthFields.TintColorInfo];

            cropGrowthInfo.TintColorInfo = TintColorInformation.ParseString(tintColorInfoString);
            if (cropGrowthInfo.TintColorInfo == null)
            {
                return(null);
            }

            return(cropGrowthInfo);
        }