async Task LoadDataFromApi()
        {
            var response = await client.GetAsync("/dates?metadata");

            if (!response.IsSuccessStatusCode)
            {
                return;
            }

            var json = await response.Content.ReadAsStringAsync();

            var dates = JsonConvert.DeserializeObject <List <VertretungsplanMetadata> >(json);

            if (dates == null)
            {
                return;
            }

            foreach (var loaded in dates)
            {
                var cached     = cache.Find(loaded.Date);
                var dateExists = cached != null;

                // New or more recent than existing version
                if (!dateExists || loaded.LastUpdated > cached.LastUpdated || loaded.Version > cached.Version)
                {
                    var dateResponse = await client.GetAsync("/dates/" + loaded.Date.ToString("yyyy-MM-dd"));

                    var dateJson = await dateResponse.Content.ReadAsStringAsync();

                    var vp = JsonConvert.DeserializeObject <Vertretungsplan>(dateJson);
                    cache.Add(vp);
                }
            }

            var oldDates = cache.GetAllDates().Except(dates.Select(vp => vp.Date)).ToList();

            foreach (var old in oldDates)
            {
                cache.Remove(old);
            }
        }
        public VertretungsplanViewModel GenerateViewModel(VertretungsplanType type, Vertretungsplan vertretungsplan)
        {
            var model = new VertretungsplanViewModel();

            model.Vertretungsplan = vertretungsplan;

            if (vertretungsplan != null)
            {
                model.Entries = vertretungsplan.Entries;

                if (type == VertretungsplanType.Teachers)
                {
                    // Change display for teacher page
                    model.Entries = model.Entries
                                    .Select(e =>
                    {
                        Entry newEntry = e.Clone();
                        // Fix cancelled lessons and changed rooms
                        if (e.SubstitutionTeacher == "—" || e.SubstitutionTeacher == "entfällt")
                        {
                            newEntry.SubstitutionTeacher = e.OriginalTeacher;
                            newEntry.OriginalTeacher     = "—";
                        }
                        if (e.SubstitutionTeacher == "entfällt")
                        {
                            if (e.Note == "—")
                            {
                                newEntry.Note = "entfällt";
                            }
                            else
                            {
                                newEntry.Note = "entfällt, " + e.Note;
                            }
                        }
                        // Change order of salutation and name
                        if (newEntry.SubstitutionTeacher.StartsWith("Frau "))
                        {
                            newEntry.SubstitutionTeacher = newEntry.SubstitutionTeacher.Substring(5) + ", Frau";
                        }
                        else if (newEntry.SubstitutionTeacher.StartsWith("Herr "))
                        {
                            newEntry.SubstitutionTeacher = newEntry.SubstitutionTeacher.Substring(5) + ", Herr";
                        }
                        return(newEntry);
                    })
                                    .OrderBy(e => e.SubstitutionTeacher)
                                    .ThenBy(e => e.Lesson)
                                    .ToList();
                }
                else if (type == VertretungsplanType.Students)
                {
                    // Filter hidden classes and teachers
                    model.Entries = model.Entries
                                    .Where(e => !(viewOptions.HiddenForms.Contains(e.Form) ||
                                                  viewOptions.HiddenTeachers.Contains(e.OriginalTeacher) ||
                                                  viewOptions.HiddenTeachers.Contains(e.SubstitutionTeacher)))
                                    .ToList();
                }

                model.LastUpdatedInWords = TimespanInWords(VertretungsplanTime.Now - model.Vertretungsplan.LastUpdated);

                model.Dates             = cache.GetAllDates().Where(e => e.Date != vertretungsplan.Date).Select(d => d.ToString(DATEFORMAT_INTERNAL)).ToList();
                model.PreviousDate      = cache.GetPrevious(vertretungsplan).Date;
                model.NextDate          = cache.GetNext(vertretungsplan).Date;
                model.DateSelectorItems = cache.GetAllDates().Select(dateOption =>
                {
                    return(new SelectListItem()
                    {
                        Text = dateOption.ToString(DATEFORMAT_PUBLIC),
                        Value = dateOption.ToString(DATEFORMAT_INTERNAL),
                        Selected = dateOption == model.Vertretungsplan.Date
                    });
                }).ToList();

                model.DateformatInternal = DATEFORMAT_INTERNAL;
                model.DateformatPublic   = DATEFORMAT_PUBLIC;
            }

            return(model);
        }