public static async Task <RaceDay> ParseFile(HorseSenseContext context, IFormFile file)
        {
            RaceDay raceDay = null;

            var lines = new List <string>();

            using (var reader = new StreamReader(file.OpenReadStream()))
            {
                var firstLine = true;
                while (reader.Peek() >= 0)
                {
                    var line = await reader.ReadLineAsync();

                    var parsedRaceday = BrisnetRtfParser.ParseLine(line);

                    if (firstLine)
                    {
                        RemoveOldDuplicateRaceDay(context, parsedRaceday);
                        firstLine = false;
                    }
                    raceDay = ParseLine(context, parsedRaceday);
                }
            }

            return(raceDay);
        }
        private static Race FindOrCreateRace(HorseSenseContext context, RaceDay raceday, RaceDay parsedRaceday)
        {
            Race race = null;

            foreach (var raceItem in raceday.Races)
            {
                if (raceItem.RaceNum == parsedRaceday.Races.First <Race>().RaceNum)
                {
                    race = raceItem;
                    return(race);
                }
            }

            if (parsedRaceday.Races != null && parsedRaceday.Races.Count > 0)
            {
                race = parsedRaceday.Races.First <Race>();
                raceday.Races.Add(race);
                context.Add(race);
                return(race);
            }
            else
            {
                return(null);
            }
        }
        private static Horse FindOrCreateHorse(HorseSenseContext context, Race race, RaceDay parsedRaceday)
        {
            Horse horse = null;

            foreach (var horseItem in race.Horses)
            {
                if (horseItem.PostPos == parsedRaceday.Races.First <Race>().Horses.First <Horse>().PostPos)
                {
                    horse = horseItem;
                    return(horse);
                }
            }


            if (parsedRaceday.Races != null &&
                parsedRaceday.Races.First <Race>().Horses != null &&
                parsedRaceday.Races.First <Race>().Horses.Count > 0)
            {
                horse = parsedRaceday.Races.First <Race>().Horses.First <Horse>();
                race.Horses.Add(horse);
                context.Add(horse);
                return(horse);
            }
            else
            {
                return(null);
            }
        }
        public async Task <IActionResult> PutRaceDay([FromRoute] int id, [FromBody] RaceDay raceDay)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            if (id != raceDay.RaceDayId)
            {
                return(BadRequest());
            }

            _context.Entry(raceDay).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!RaceDayExists(id))
                {
                    return(NotFound());
                }
                else
                {
                    throw;
                }
            }

            return(NoContent());
        }
        public void InsertMultipleRaceDaysTest()
        {
            using (var context = new HorseSenseContext(GetHorseSenseContextOptionForMethod()))
            {
                var raceday = new RaceDay()
                {
                    Track = "TestTrack",
                    Date  = "20180102"
                };
                var racedayNewDate = new RaceDay()
                {
                    Track = "TestTrack",
                    Date  = "20180103"
                };
                var racedayNewTrack = new RaceDay()
                {
                    Track = "AnotherTrack",
                    Date  = "20180102"
                };
                DrfParser.ParseLine(context, raceday);
                DrfParser.ParseLine(context, racedayNewDate);
                DrfParser.ParseLine(context, racedayNewTrack);

                Assert.AreEqual(3, context.RaceDays.Count(), "Incorrect number of raceDays");
                Assert.IsNotNull(context.RaceDays.FirstOrDefault(r =>
                                                                 r.Track == "TestTrack" && r.Date == "20180102"));
                Assert.AreEqual(1, context.RaceDays.Where(r =>
                                                          r.Track == "TestTrack" && r.Date == "20180103").Count());
                Assert.AreEqual(1, context.RaceDays.Where(r =>
                                                          r.Track == "AnotherTrack" && r.Date == "20180102").Count());
            }
        }
        ////////        //*** Today's Race Data ***
        ////////        public string Track { get; set; }
        ////////        Date { get; set; }
        ////////    RaceNumber             { get; set; }
        ////////PostPosition { get; set; }
        ////////        Entry { get; set; }
        ////////        Distance  { get; set; }   // (in yards)
        ////////        Surface { get; set; }
        ////////        Reserved { get; set; }
        ////////        RaceType { get; set; }
        ////////        AgeSexRestrictions { get; set; }
        ////////        RaceClassification { get; set; }
        ////////        Purse { get; set; }
        ////////        ClaimingPrice { get; set; }
        ////////        ClaimingPriceOfHorse { get; set; }
        ////////        TrackRecord { get; set; }
        ////////        RaceConditions { get; set; }


        public static RaceDay ParseLine(string line)
        {
            var elements = line.Split(',');

            Console.WriteLine("Parsed line has {0} elements", elements.Length);
            if (elements.Length < EXPECTED_ELEMENT_COUNT - 1)
            {
                Console.WriteLine("!!!! BrisnetRtfParser.ParseLine:  Invalid line. Line only contains {0} elements, expected {1} !!!!", elements.Length, EXPECTED_ELEMENT_COUNT);
            }

            var raceDay = new RaceDay
            {
                Track = elements[0],
                Date  = elements[1]
            };

            var race = new Race();

            {
                race.RaceNum  = int.Parse(elements[2]);
                race.Distance = int.Parse(elements[5]);
                race.Surface  = elements[6];
                race.RaceType = elements[8];
                race.Sex      = elements[9].Substring(2, 1);
                race.Purse    = int.Parse(elements[11]);
                int.TryParse(elements[12], out int claimingPrice);
                race.ClaimingPrice  = claimingPrice;
                race.RaceConditions = elements[15];
            };
            raceDay.Races.Add(race);

            //////public int TrackStarts { get; set; }
            //////public int TrackWins { get; set; }
            //////public int TStarts { get; set; }
            //////public int TWins { get; set; }
            //////public int TPlaces { get; set; }
            //////public int TShows { get; set; }
            //////public int LStarts { get; set; }
            //////public int LWins { get; set; }
            //////public string TrackWkt { get; set; }
            //////public double WinPercentage { get; set; }
            ///////public bool Scratch { get; set; }

            var horse = new Horse
            {
                PostPos     = int.Parse(elements[3]),
                Trainer     = elements[27],
                Jockey      = elements[34],
                MorningLine = Double.Parse(elements[43]),
                Name        = elements[44]
            };

            race.Horses.Add(horse);

            return(raceDay);
        }
        public async Task <IActionResult> PostRaceDay([FromBody] RaceDay raceDay)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            _context.RaceDays.Add(raceDay);
            await _context.SaveChangesAsync();

            return(CreatedAtAction("GetRaceDay", new { id = raceDay.RaceDayId }, raceDay));
        }
        // @@@@@ TODO: Make private but allow unit testing
        public static RaceDay ParseLine(HorseSenseContext context, RaceDay parsedRaceday)
        {
            var raceday = FindOrCreateRaceDay(context, parsedRaceday);

            if (raceday != null)
            {
                var race = FindOrCreateRace(context, raceday, parsedRaceday);
                if (race != null)
                {
                    var horse = FindOrCreateHorse(context, race, parsedRaceday);
                }
            }
            context.SaveChanges();

            return(raceday);
        }
        private static void RemoveOldDuplicateRaceDay(HorseSenseContext context, RaceDay parsedRaceday)
        {
            var foundRaceDay = context.RaceDays
                               //.Include(rd => rd.Races)
                               //.ThenInclude(r => r.Horses)
                               .FirstOrDefault
                                   (rd => rd.Track.Equals(parsedRaceday.Track) &&
                                   rd.Date.Equals(parsedRaceday.Date));

            if (foundRaceDay != null)
            {
                // Cascade delete is enabled by default in Entity Framework, this will remove raceday and its races & horses
                // @@@@@@ But this doesn't seem to work !!!!!
                context.RaceDays.Remove(foundRaceDay);
                context.SaveChanges();
            }
        }
        public void DuplicateInsertRaceDayTest()
        {
            using (var context = new HorseSenseContext(GetHorseSenseContextOptionForMethod()))
            {
                var raceday = new RaceDay()
                {
                    Track = "TestTrack",
                    Date  = "20180102"
                };

                DrfParser.ParseLine(context, raceday);
                DrfParser.ParseLine(context, raceday);

                Assert.AreEqual(1, context.RaceDays.Count());
                Assert.AreEqual("TestTrack", context.RaceDays.Single().Track);
                Assert.AreEqual("20180102", context.RaceDays.Single().Date);
            }
        }
        private static RaceDay FindOrCreateRaceDay(HorseSenseContext context, RaceDay parsedRaceday)
        {
            RaceDay raceDay = context.RaceDays
                              .Include(rd => rd.Races)
                              .ThenInclude(r => r.Horses)
                              .FirstOrDefault(rd => rd.Track.Equals(parsedRaceday.Track) && rd.Date.Equals(parsedRaceday.Date));

            if (raceDay == null)
            {
                raceDay = new RaceDay
                {
                    Track = parsedRaceday.Track,
                    Date  = parsedRaceday.Date
                };

                context.Add(raceDay);
            }

            return(raceDay);
        }