//
// Copyright (C) 2023 - 2025 Sven Dmitrienko <svens@svens-tools.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
//
////////////////////////////////////////////////////////////////////////////////

unit UnitMainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, System.Generics.Collections, Vcl.Graphics, Vcl.Controls,
  Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.ComCtrls, Vcl.StdCtrls, UnitDiary,
  System.ImageList, Vcl.ImgList, Vcl.ToolWin, Vcl.ExtCtrls, VclTee.TeeGDIPlus,
  VCLTee.TeEngine, VCLTee.TeeProcs, VCLTee.Chart, VCLTee.Series;

type
  TmainForm = class(TForm)
    MainMenu: TMainMenu;
    MainMenuFile: TMenuItem;
    MenuItemOpenFile: TMenuItem;
    MenuItemSave: TMenuItem;
    MenuItemSaveAs: TMenuItem;
    N1: TMenuItem;
    MenuItemExit: TMenuItem;
    PageControlAll: TPageControl;
    TabSheetTasks: TTabSheet;
    TabSheetMeals: TTabSheet;
    TabSheetHealth: TTabSheet;
    TabSheetWeather: TTabSheet;
    TabSheetThoughts: TTabSheet;
    RichEditWhatHappenedAdditionalyToTheTasks: TRichEdit;
    RichEditBreakfast: TRichEdit;
    RichEditLunch: TRichEdit;
    RichEditDinner: TRichEdit;
    RichEditThoughts: TRichEdit;
    LabelWhatHappenedAdditionalyToTheTasks: TLabel;
    LabelBreakfast: TLabel;
    LabelLunch: TLabel;
    LabelDinner: TLabel;
    GroupBoxAtMorning: TGroupBox;
    LabelTemperature1: TLabel;
    LabelPuls1: TLabel;
    LabelBloodPressureSys1: TLabel;
    LabelBloodPressureDia1: TLabel;
    LabelOxygenSaturation1: TLabel;
    LabelWeight1: TLabel;
    EditTemperature1: TEdit;
    EditPuls1: TEdit;
    EditBloodPressureSys1: TEdit;
    EditBloodPressureDia1: TEdit;
    EditOxygenSaturation1: TEdit;
    EditWeight1: TEdit;
    GroupBoxAtLunch: TGroupBox;
    LabelTemperature2: TLabel;
    LabelPuls2: TLabel;
    LabelBloodPressureSys2: TLabel;
    LabelBloodPressureDia2: TLabel;
    LabelOxygenSaturation2: TLabel;
    LabelWeight2: TLabel;
    EditTemperature2: TEdit;
    EditPuls2: TEdit;
    EditBloodPressureSys2: TEdit;
    EditBloodPressureDia2: TEdit;
    EditOxygenSaturation2: TEdit;
    EditWeight2: TEdit;
    GroupBoxAtEvening: TGroupBox;
    LabelTemperature3: TLabel;
    LabelPuls3: TLabel;
    LabelBloodPressureSys3: TLabel;
    LabelBloodPressureDia3: TLabel;
    LabelOxygenSaturation3: TLabel;
    LabelWeight3: TLabel;
    EditTemperature3: TEdit;
    EditPuls3: TEdit;
    EditBloodPressureSys3: TEdit;
    EditBloodPressureDia3: TEdit;
    EditOxygenSaturation3: TEdit;
    EditWeight3: TEdit;
    DateTimePicker1: TDateTimePicker;
    LabelDate: TLabel;
    MainMenuHelp: TMenuItem;
    MenuItemAbout: TMenuItem;
    SaveDialog1: TSaveDialog;
    OpenDialog1: TOpenDialog;
    MainMenuExport: TMenuItem;
    MenuItemExportSelectedMonthAsTextfile: TMenuItem;
    MenuItemNew: TMenuItem;
    CheckBoxHeartArrhythmiaSymbolAppears1: TCheckBox;
    CheckBoxHeartArrhythmiaSymbolAppears2: TCheckBox;
    CheckBoxHeartArrhythmiaSymbolAppears3: TCheckBox;
    EditGlucoseLevel1: TEdit;
    LabelGlucoseLevel1: TLabel;
    LabelGlucoseLevel2: TLabel;
    EditGlucoseLevel2: TEdit;
    LabelGlucoseLevel3: TLabel;
    EditGlucoseLevel3: TEdit;
    MenuItemExporthealthvaluesoftheselectedmonthasaCSVfile1: TMenuItem;
    ToolBar1: TToolBar;
    ToolButtonExit: TToolButton;
    ImageList1: TImageList;
    ToolButtonSaveFile: TToolButton;
    ToolButtonSaveFileAs: TToolButton;
    ToolButtonOpenFile: TToolButton;
    ToolButtonOpenNewFile: TToolButton;
    ToolButton6: TToolButton;
    LabelDayOfWeek: TLabel;
    GroupBoxTemperatureMorning: TGroupBox;
    LabelTemperatureMorning: TLabel;
    EditWeatherTemperatureMorning: TEdit;
    GroupBoxTemperatureAfternoon: TGroupBox;
    LabelTemperatureAfternoon: TLabel;
    EditWeatherTemperatureAfternoon: TEdit;
    GroupBoxTemperatureEvening: TGroupBox;
    LabelTemperatureEvening: TLabel;
    EditWeatherTemperatureEvening: TEdit;
    GroupBoxTemperatureOvernight: TGroupBox;
    LabelTemperatureOvernight: TLabel;
    EditWeatherTemperatureOvernight: TEdit;
    GroupBoxAfternoon: TGroupBox;
    LabelHumidity: TLabel;
    LabelUVIndex: TLabel;
    EditWeatherUVIndex: TEdit;
    EditWeatherHumidity: TEdit;
    LabelPressure: TLabel;
    EditWeatherPressure: TEdit;
    LabelWindDirection: TLabel;
    LabelWindSpeed: TLabel;
    EditWeatherWindSpeed: TEdit;
    ComboBoxWeatherWindDirection: TComboBox;
    TabSheetPicture: TTabSheet;
    ImageOfTheDay: TImage;
    ButtonLoadPictureFromFile: TButton;
    ButtonDeleteJpg: TButton;
    N2: TMenuItem;
    MenuItemRecentFiles: TMenuItem;
    MenuItemRecentFile1: TMenuItem;
    MenuItemRecentFile2: TMenuItem;
    MenuItemRecentFile3: TMenuItem;
    MenuItemRecentFile4: TMenuItem;
    MenuItemRecentFile5: TMenuItem;
    MenuItemRecentFile6: TMenuItem;
    PageControlHealth: TPageControl;
    TabSheetHealthCondition: TTabSheet;
    TabSheetHealthChart: TTabSheet;
    RichEditlHealthCondition: TRichEdit;
    LabelHealthValue: TLabel;
    ComboBoxHealthValue: TComboBox;
    ChartHealthValue: TChart;
    Series1: TLineSeries;
    Series2: TLineSeries;
    Series3: TLineSeries;
    PageControlWeather: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    LabelWeatherValue: TLabel;
    ComboBoxWeatherValue: TComboBox;
    ChartWeatherValue: TChart;
    LineSeries1: TLineSeries;
    RichEditWeatherToday: TRichEdit;
    ComboBoxWeatherMoonPhase: TComboBox;
    LabelWeatherMoonPhase: TLabel;
    MainMenuImport: TMenuItem;
    MenuItemImportTasksFromACSVFile: TMenuItem;
    RadioGroupChartType: TRadioGroup;
    ButtonGoToLastFilledDay: TButton;
    ButtonGoToFirstFilledDay: TButton;
    TabSheetConversations: TTabSheet;
    RichEditConversation: TRichEdit;
    LabelConversation: TLabel;
    ButtonAddConversation: TButton;
    ButtonDeleteConversation: TButton;
    ListViewConversations: TListView;
    DateTimePickerFrom: TDateTimePicker;
    DateTimePickerTo: TDateTimePicker;
    LabelFromTime: TLabel;
    LabelToTime: TLabel;
    EditConversationTitle: TEdit;
    LabelConversationTitle: TLabel;
    ButtonGoToPreviousFilledDay: TButton;
    ButtonGoToNextFilledDay: TButton;
    RichEditTeeCoffeeTime: TRichEdit;
    LabelTeeCoffeeTime: TLabel;
    RichEditBrunch: TRichEdit;
    LabelBrunch: TLabel;
    TabSheetShopping: TTabSheet;
    ListViewShoppings: TListView;
    RichEditShoppingList: TRichEdit;
    EditShop: TEdit;
    LabelShop: TLabel;
    LabelShoppingFrom: TLabel;
    DateTimePickerShoppingFrom: TDateTimePicker;
    LabelShoppingTo: TLabel;
    DateTimePickerShoppingTo: TDateTimePicker;
    LabelShoppingList: TLabel;
    ButtonAddShopping: TButton;
    ButtonDeleteShopping: TButton;
    LabelTotalPurchaseAmount: TLabel;
    EditTotalPurchaseAmount: TEdit;
    ListViewTasks: TListView;
    LabelTaskFrom: TLabel;
    DateTimePickerTaskFrom: TDateTimePicker;
    LabelTaskTo: TLabel;
    DateTimePickerTaskTo: TDateTimePicker;
    LabelTask: TLabel;
    EditTask: TEdit;
    LabelNotes: TLabel;
    RichEditNotes: TRichEdit;
    ButtonAddTask: TButton;
    ButtonDeleteTask: TButton;
    LabelTotalAmountOfPurchaes1: TLabel;
    LabelTotalAmountOfPurchaes2: TLabel;
    procedure MenuItemExitClick(Sender: TObject);
    procedure MenuItemOpenFileClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure DateTimePicker1Change(Sender: TObject);
    procedure MenuItemSaveAsClick(Sender: TObject);
    procedure MenuItemSaveClick(Sender: TObject);
    procedure MenuItemAboutClick(Sender: TObject);
    procedure MenuItemExportSelectedMonthAsTextfileClick(Sender: TObject);
    procedure MenuItemNewClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure MenuItemExporthealthvaluesoftheselectedmonthasaCSVfile1Click(
      Sender: TObject);
    procedure ToolButtonExitClick(Sender: TObject);
    procedure ToolButtonSaveFileClick(Sender: TObject);
    procedure ToolButtonSaveFileAsClick(Sender: TObject);
    procedure ToolButtonOpenFileClick(Sender: TObject);
    procedure ToolButtonOpenNewFileClick(Sender: TObject);
    procedure CheckKeyPressForFloatingPointNumbers(Sender: TObject; var Key: Char);
    procedure CheckKeyPressForIntegerNumbers(Sender: TObject; var Key: Char);
    procedure CheckKeyPressForIntegerNumbersAndMinusSign(Sender: TObject; var Key: Char);
    procedure CatchEmptyNumberFieldsOnExit(Sender: TObject);
    procedure ButtonLoadPictureFromFileClick(Sender: TObject);
    procedure ButtonDeleteJpgClick(Sender: TObject);
    procedure MenuItemRecentFile1Click(Sender: TObject);
    procedure MenuItemRecentFile2Click(Sender: TObject);
    procedure MenuItemRecentFile3Click(Sender: TObject);
    procedure MenuItemRecentFile4Click(Sender: TObject);
    procedure MenuItemRecentFile5Click(Sender: TObject);
    procedure MenuItemRecentFile6Click(Sender: TObject);
    procedure ComboBoxHealthValueChange(Sender: TObject);
    procedure ComboBoxWeatherValueChange(Sender: TObject);
    procedure MenuItemImportTasksFromACSVFileClick(Sender: TObject);
    procedure RadioGroupChartTypeClick(Sender: TObject);
    procedure ButtonGoToLastFilledDayClick(Sender: TObject);
    procedure ButtonGoToFirstFilledDayClick(Sender: TObject);
    procedure CheckOnChange(Sender: TObject);
    procedure RichEditKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure ButtonAddConversationClick(Sender: TObject);
    procedure ButtonDeleteConversationClick(Sender: TObject);
    procedure DateTimePickerFromChange(Sender: TObject);
    procedure DateTimePickerToChange(Sender: TObject);
    procedure EditConversationTitleChange(Sender: TObject);
    procedure ListViewConversationsClick(Sender: TObject);
    procedure ButtonGoToNextFilledDayClick(Sender: TObject);
    procedure ButtonGoToPreviousFilledDayClick(Sender: TObject);
    procedure ButtonAddShoppingClick(Sender: TObject);
    procedure ButtonDeleteShoppingClick(Sender: TObject);
    procedure ListViewShoppingsClick(Sender: TObject);
    procedure DateTimePickerShoppingFromChange(Sender: TObject);
    procedure DateTimePickerShoppingToChange(Sender: TObject);
    procedure EditShopChange(Sender: TObject);
    procedure EditTotalPurchaseAmountChange(Sender: TObject);
    procedure EditTaskChange(Sender: TObject);
    procedure DateTimePickerTaskFromChange(Sender: TObject);
    procedure DateTimePickerTaskToChange(Sender: TObject);
    procedure ListViewTasksClick(Sender: TObject);
    procedure ButtonAddTaskClick(Sender: TObject);
    procedure ButtonDeleteTaskClick(Sender: TObject);
  private
    var
      fBusy: Boolean;
      fBytes: TBytes;
      fConversation: TConversation;
      fDay: TDay;
      fDialogUpdated: Boolean;
      fDiary: TDiary;
      fFileName: String;
      fShopping: TShopping;
      fTask: TTask;
    procedure Ask(Sender: TObject);
    procedure EnableConversationElements(const aEnabled: Boolean);
    procedure EnableShoppingElements(const aEnabled: Boolean);
    procedure EnableTaskElements(const aEnabled: Boolean);
    procedure FillListViewConversations;
    procedure FillListViewShoppings;
    procedure FillListViewTasks;
    procedure GetData;
    procedure GetDataConversation;
    procedure GetDataShopping;
    procedure GetDataTask;
    function GetDialogUpdated: Boolean;
    function NotEmptyDayFound(const aDay: TDay): Boolean;
    function Open: Boolean;
    procedure OpenNewFile;
    procedure OpenRecentFile(
      Sender: TObject;
      aFileName: String);
    procedure Save;
    procedure SearchActualMonth(
      aListOfFilteredDays: TObjectList<TDay>;
      aSearchYear: Integer;
      aSearchMonth: Byte);
    procedure SearchLast30Days(aListOfFilteredDays: TObjectList<TDay>);
    procedure SecurePicture;
    procedure SelectItemInListViewConversations;
    procedure SelectItemInListViewShoppings;
    procedure SelectItemInListViewTasks;
    procedure SetData;
    procedure SetDataConversation;
    procedure SetDataShopping;
    procedure SetDataTask;
    procedure SetDialogUpdated(const aValue: Boolean);
    procedure TestData;
    procedure UpdateListViewConversations;
    procedure UpdateListViewShoppings;
    procedure UpdateListViewTasks;
    procedure UpdateHealthChart;
    procedure UpdateMenuItemsRecentFiles;
    procedure UpdateWeatherChart;
    property DialogUpdated: Boolean read GetDialogUpdated write SetDialogUpdated;
  public
    { Public-Deklarationen }
  end;

var
  mainForm: TmainForm;

implementation

uses
  DateUtils, System.Generics.Defaults, System.UITypes,
  Vcl.Imaging.jpeg, UnitAbout, sdFileUtils, sdDateUtils, sdByteUtils;

{$R *.dfm}

procedure TmainForm.Ask(Sender: TObject);
begin
  CatchEmptyNumberFieldsOnExit(Sender);
  if (DialogUpdated) then
  begin
    if ( MessageDlg('Do you want to save the file?',
                     mtConfirmation,
                     [mbYes, mbNo],
                     0,
                     mbYes) = mrYes ) then
    begin
      if (fFileName <> '') then
      begin
        SecurePicture;
        Save;
      end
      else
      begin
        fBusy := False;
        MenuItemSaveAsClick(Sender);
        fBusy := True;
      end;
    end
    else
      CatchEmptyNumberFieldsOnExit(Sender);
  end;
end;

procedure TmainForm.ButtonAddConversationClick(Sender: TObject);
var
  a_Conversation: TConversation;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    SetDataConversation;
    a_Conversation := TConversation.Create;
    fDay.LastConversationID := fDay.LastConversationID + 1;
    a_Conversation.ID := fDay.LastConversationID;
    fDay.Conversations.Add(a_Conversation);
    fConversation := a_Conversation;
    FillListViewConversations;
    SelectItemInListViewConversations;
    GetDataConversation;
    EnableConversationElements(True);
    DialogUpdated := True;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonAddShoppingClick(Sender: TObject);
var
  a_Shopping: TShopping;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    SetDataShopping;
    a_Shopping := TShopping.Create;
    fDay.LastShoppingID := fDay.LastShoppingID + 1;
    a_Shopping.ID := fDay.LastShoppingID;
    fDay.Shoppings.Add(a_Shopping);
    fShopping := a_Shopping;
    FillListViewShoppings;
    SelectItemInListViewShoppings;
    GetDataShopping;
    EnableShoppingElements(True);
    DialogUpdated := True;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonAddTaskClick(Sender: TObject);
var
  a_Task: TTask;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    SetDataTask;
    a_Task := TTask.Create;
    fDay.LastTaskID := fDay.LastTaskID + 1;
    a_Task.ID := fDay.LastTaskID;
    fDay.Tasks.Add(a_Task);
    fTask := a_Task;
    FillListViewTasks;
    SelectItemInListViewTasks;
    GetDataTask;
    EnableTaskElements(True);
    DialogUpdated := True;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;end;

procedure TmainForm.ButtonDeleteConversationClick(Sender: TObject);
var
  i: Int64;
  a_Conversation: TConversation;
  a_Conversation2: TConversation;
  a_ListItem: TListItem;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    a_Conversation := ListViewConversations.Selected.Data;
    for i := 0 to fDay.Conversations.Count - 1 do
    begin
      a_Conversation2 :=  fDay.Conversations[i];
      if ( a_Conversation.ID = a_Conversation2.ID ) then
      begin
        fDay.Conversations.Delete(i);
        Break;
      end;
    end;
    FillListViewConversations;
    if (fDay.Conversations.Count > 0) then
    begin
      a_ListItem := ListViewConversations.Items.Item[0];
      a_ListItem.Selected := True;
      fConversation := fDay.Conversations[0];
      GetDataConversation;
      EnableConversationElements(True);
    end
    else
    begin
      fConversation := nil;
      EnableConversationElements(False);
    end;
    DialogUpdated := True;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonDeleteJpgClick(Sender: TObject);
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    ImageOfTheDay.Picture.Assign(nil);
    SetLength(fBytes, 0);
    TestData;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonDeleteShoppingClick(Sender: TObject);
var
  i: Int64;
  a_Shopping: TShopping;
  a_Shopping2: TShopping;
  a_ListItem: TListItem;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    a_Shopping := ListViewShoppings.Selected.Data;
    for i := 0 to fDay.Shoppings.Count - 1 do
    begin
      a_Shopping2 :=  fDay.Shoppings[i];
      if ( a_Shopping.ID = a_Shopping2.ID ) then
      begin
        fDay.Shoppings.Delete(i);
        Break;
      end;
    end;
    FillListViewShoppings;
    if (fDay.Shoppings.Count > 0) then
    begin
      a_ListItem := ListViewShoppings.Items.Item[0];
      a_ListItem.Selected := True;
      fShopping := fDay.Shoppings[0];
      GetDataShopping;
      EnableShoppingElements(True);
    end
    else
    begin
      fShopping := nil;
      EnableShoppingElements(False);
    end;
    DialogUpdated := True;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonDeleteTaskClick(Sender: TObject);
var
  i: Int64;
  a_Task: TTask;
  a_Task2: TTask;
  a_ListItem: TListItem;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    a_Task := ListViewTasks.Selected.Data;
    for i := 0 to fDay.Tasks.Count - 1 do
    begin
      a_Task2 :=  fDay.Tasks[i];
      if ( a_Task.ID = a_Task2.ID ) then
      begin
        fDay.Tasks.Delete(i);
        Break;
      end;
    end;
    FillListViewTasks;
    if (fDay.Tasks.Count > 0) then
    begin
      a_ListItem := ListViewTasks.Items.Item[0];
      a_ListItem.Selected := True;
      fTask := fDay.Tasks[0];
      GetDataTask;
      EnableTaskElements(True);
    end
    else
    begin
      fTask := nil;
      EnableTaskElements(False);
    end;
    DialogUpdated := True;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonGoToFirstFilledDayClick(Sender: TObject);
var
  i: Int64;
  a_Day: TDay;
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    CatchEmptyNumberFieldsOnExit(nil);
    if (fDiary.DB.Count > 0) then
    begin
      fDiary.DB.Sort(TComparer<TDay>.Construct(
          function (const Left, Right: TDay): Integer
          begin
            Result := CompareDate(Left.Date, Right.Date);
          end
        )
      );
      a_Day := fDay;
      for i := 0 to fDiary.DB.Count - 1 do
      begin
        a_Day := fDiary.DB.Items[i];
        if (NotEmptyDayFound(a_Day)) then
          Break;
      end;
      if (Assigned(a_Day))then
      begin
        fDay := a_Day;
        DateTimePicker1.Date := fDay.Date;
        GetData;
      end;
    end;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonGoToLastFilledDayClick(Sender: TObject);
var
  i: Int64;
  a_Day: TDay;
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    Screen.Cursor := crHourGlass;
    try
      CatchEmptyNumberFieldsOnExit(nil);
      if (fDiary.DB.Count > 0) then
      begin
        fDiary.DB.Sort(TComparer<TDay>.Construct(
            function (const Left, Right: TDay): Integer
            begin
              Result := CompareDate(Left.Date, Right.Date);
            end
          )
        );
        a_Day := fDay;
        for i := fDiary.DB.Count - 1 downto 0 do
        begin
          a_Day := fDiary.DB.Items[i];
          if (NotEmptyDayFound(a_Day)) then
            Break;
        end;
        if (Assigned(a_Day))then
        begin
          fDay := a_Day;
          DateTimePicker1.Date := fDay.Date;
          GetData;
        end;
      end;
    finally
      Screen.Cursor := crDefault;
    end;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.ButtonGoToNextFilledDayClick(Sender: TObject);
var
  i,j: Int64;
  a_Day, a_Day2: TDay;
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    CatchEmptyNumberFieldsOnExit(nil);
    if (fDiary.DB.Count > 0) then
    begin
      fDiary.DB.Sort(TComparer<TDay>.Construct(
            function (const Left, Right: TDay): Integer
            begin
              Result := CompareDate(Left.Date, Right.Date);
            end
          )
      );
      a_Day2 := fDay;
      j := fDiary.DB.IndexOf(fDay);
      if ((j + 1) > (fDiary.DB.Count - 1)) then
      begin
        for i := 0 to fDiary.DB.Count - 1 do
        begin
          a_Day := fDiary.DB.Items[i];
          if (NotEmptyDayFound(a_Day)) then
            a_Day2 := a_Day;
        end;
      end
      else
        for i := j + 1 to fDiary.DB.Count - 1 do
        begin
          a_Day := fDiary.DB.Items[i];
          if (NotEmptyDayFound(a_Day)) then
          begin
            a_Day2 := a_Day;
            Break;
          end;
        end;
      if (Assigned(a_Day2)) then
      begin
        fDay := a_Day2;
        DateTimePicker1.Date := fDay.Date;
        GetData;
      end;
    end;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonGoToPreviousFilledDayClick(Sender: TObject);
var
  i,j: Int64;
  a_Day, a_Day2: TDay;
  a_Result: Integer;
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    CatchEmptyNumberFieldsOnExit(nil);
    if (fDiary.DB.Count > 0) then
    begin
      fDiary.DB.Sort(TComparer<TDay>.Construct(
          function (const Left, Right: TDay): Integer
          begin
            Result := CompareDate(Left.Date, Right.Date);
          end
        )
      );
      a_Day2 := fDay;
      j := fDiary.DB.IndexOf(fDay);
      for i := 0 to j do
      begin
        a_Day := fDiary.DB.Items[i];
        if (NotEmptyDayFound(a_Day)) then
        begin
          a_Result := CompareDate(fDay.Date, a_Day.Date);
          if (a_Result = 0) then
            Break
          else
            a_Day2 := a_Day;
        end;
      end;
      if (Assigned(a_Day2)) then
      begin
        fDay := a_Day2;
        DateTimePicker1.Date := fDay.Date;
        GetData;
      end;
    end;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ButtonLoadPictureFromFileClick(Sender: TObject);
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    OpenDialog1.FileName := ExtractFilePath(fFileName);
    OpenDialog1.Filter := 'JPG Files (*.jpg)|*.jpg';
    if (OpenDialog1.Execute) then
      if (FileExists(OpenDialog1.FileName)) then
        ImageOfTheDay.Picture.LoadFromFile(OpenDialog1.FileName)
      else
        ShowMessage('File ' + OpenDialog1.FileName + ' does not exist.');
    TestData;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.CatchEmptyNumberFieldsOnExit(Sender: TObject);
begin
  if (Sender <> nil) then
  begin
    if (fBusy = True) then
      Exit;
    fBusy := True;
  end;
  try
    if (Sender <> nil) then
      Screen.Cursor := crHourGlass;
    try
      if EditTemperature1.Text = '' then
        EditTemperature1.Text := '0';
      if EditPuls1.Text = '' then
        EditPuls1.Text := '0';
      if EditBloodPressureSys1.Text = '' then
        EditBloodPressureSys1.Text := '0';
      if EditBloodPressureDia1.Text = '' then
        EditBloodPressureDia1.Text := '0';
      if EditOxygenSaturation1.Text = '' then
        EditOxygenSaturation1.Text := '0';
      if EditGlucoseLevel1.Text = '' then
        EditGlucoseLevel1.Text := '0';
      if EditWeight1.Text = '' then
        EditWeight1.Text := '0';
      if EditTemperature2.Text = '' then
        EditTemperature2.Text := '0';
      if EditPuls2.Text = '' then
        EditPuls2.Text := '0';
      if EditBloodPressureSys2.Text = '' then
        EditBloodPressureSys2.Text := '0';
      if EditBloodPressureDia2.Text = '' then
        EditBloodPressureDia2.Text := '0';
      if EditOxygenSaturation2.Text = '' then
        EditOxygenSaturation2.Text := '0';
      if EditGlucoseLevel2.Text = '' then
        EditGlucoseLevel2.Text := '0';
      if EditWeight2.Text = '' then
        EditWeight2.Text := '0';
      if EditTemperature3.Text = '' then
        EditTemperature3.Text := '0';
      if EditPuls3.Text = '' then
        EditPuls3.Text := '0';
      if EditBloodPressureSys3.Text = '' then
        EditBloodPressureSys3.Text := '0';
      if EditBloodPressureDia3.Text = '' then
        EditBloodPressureDia3.Text := '0';
      if EditOxygenSaturation3.Text = '' then
        EditOxygenSaturation3.Text := '0';
      if EditGlucoseLevel3.Text = '' then
        EditGlucoseLevel3.Text := '0';
      if EditWeight3.Text = '' then
        EditWeight3.Text := '0';
      if EditWeatherHumidity.Text = '' then
        EditWeatherHumidity.Text := '0';
      if EditWeatherPressure.Text = '' then
        EditWeatherPressure.Text := '0';
      if (EditWeatherTemperatureAfternoon.Text = '') or (EditWeatherTemperatureAfternoon.Text = '-') then
        EditWeatherTemperatureAfternoon.Text := '0';
      if (EditWeatherTemperatureEvening.Text = '') or (EditWeatherTemperatureEvening.Text = '-') then
        EditWeatherTemperatureEvening.Text := '0';
      if (EditWeatherTemperatureMorning.Text = '') or (EditWeatherTemperatureMorning.Text = '-') then
        EditWeatherTemperatureMorning.Text := '0';
      if (EditWeatherTemperatureOvernight.Text = '') or (EditWeatherTemperatureOvernight.Text = '-') then
        EditWeatherTemperatureOvernight.Text := '0';
      if EditWeatherWindSpeed.Text = '' then
        EditWeatherWindSpeed.Text := '0';
      if EditWeatherUVIndex.Text = '' then
        EditWeatherUVIndex.Text := '0';
      if EditTotalPurchaseAmount.Text = '' then
        EditTotalPurchaseAmount.Text := '0';
      TestData;
      SetData;
      UpdateHealthChart;
      UpdateWeatherChart;
    finally
      if (Sender <> nil) then
        Screen.Cursor := crDefault;
    end;
  finally
    if (Sender <> nil) then
      fBusy := False;
  end;
end;

procedure TmainForm.CheckKeyPressForFloatingPointNumbers(Sender: TObject; var Key: Char);
begin
  if (Key <> #08) then
    if ((Key < '0') or (Key > '9'))  then
    begin
      if ((Pos(FormatSettings.DecimalSeparator, (Sender as TEdit).Text) = 0) and (Key = FormatSettings.DecimalSeparator))then
      else
      begin
        MessageDlg('Only floating point numbers are allowed!', mtError, [mbOK], 0, mbOK);
        Key := Chr(27);
      end;
    end;
end;

procedure TmainForm.CheckKeyPressForIntegerNumbers(Sender: TObject; var Key: Char);
begin
  if (Key <> #08) then
    if ((Key < '0') or (Key > '9'))  then
    begin
      MessageDlg('Only integers are allowed!', mtError, [mbOK], 0, mbOK);
      Key := Chr(27);
    end;
end;

procedure TmainForm.CheckKeyPressForIntegerNumbersAndMinusSign(Sender: TObject; var Key: Char);
begin
  if ((Key <> #08) and (Key <> '-')) then
    if ((Key < '0') or (Key > '9'))  then
    begin
      MessageDlg('Only integers are allowed!', mtError, [mbOK], 0, mbOK);
      Key := Chr(27);
    end;
end;

procedure TmainForm.CheckOnChange(Sender: TObject);
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
   TestData;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ComboBoxHealthValueChange(Sender: TObject);
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    UpdateHealthChart;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ComboBoxWeatherValueChange(Sender: TObject);
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    UpdateWeatherChart;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.DateTimePicker1Change(Sender: TObject);
var
  a_Day: TDay;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    CatchEmptyNumberFieldsOnExit(nil);
    a_Day := fDiary.GetDay(DateTimePicker1.DateTime);
    if (not SameDate(fDay.Date, a_Day.Date)) then
    begin
      fDay := a_Day;
      GetData;
    end;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.DateTimePickerFromChange(Sender: TObject);
begin
  UpdateListViewConversations;
end;

procedure TmainForm.DateTimePickerShoppingFromChange(Sender: TObject);
begin
  UpdateListViewShoppings;
end;

procedure TmainForm.DateTimePickerShoppingToChange(Sender: TObject);
begin
  UpdateListViewShoppings;
end;

procedure TmainForm.DateTimePickerTaskFromChange(Sender: TObject);
begin
  UpdateListViewTasks;
end;

procedure TmainForm.DateTimePickerTaskToChange(Sender: TObject);
begin
  UpdateListViewTasks;
end;

procedure TmainForm.DateTimePickerToChange(Sender: TObject);
begin
  UpdateListViewConversations;
end;

procedure TmainForm.EditConversationTitleChange(Sender: TObject);
begin
  UpdateListViewConversations;
end;

procedure TmainForm.EditShopChange(Sender: TObject);
begin
  UpdateListViewShoppings;
end;

procedure TmainForm.EditTaskChange(Sender: TObject);
begin
  UpdateListViewTasks;
end;

procedure TmainForm.EditTotalPurchaseAmountChange(Sender: TObject);
begin
  UpdateListViewShoppings;
end;

procedure TmainForm.EnableConversationElements(const aEnabled: Boolean);
begin
  DateTimePickerFrom.Enabled := aEnabled;
  DateTimePickerTo.Enabled := aEnabled;
  EditConversationTitle.Enabled := aEnabled;
  RichEditConversation.Enabled := aEnabled;
  ButtonDeleteConversation.Enabled := aEnabled;
  if (not aEnabled) then
  begin
    DateTimePickerFrom.Time := Time;
    DateTimePickerTo.Time := Time;
    EditConversationTitle.Text := '';
    RichEditConversation.Text := '';
  end;
end;

procedure TmainForm.EnableShoppingElements(const aEnabled: Boolean);
begin
  DateTimePickerShoppingFrom.Enabled := aEnabled;
  DateTimePickerShoppingTo.Enabled := aEnabled;
  EditShop.Enabled := aEnabled;
  RichEditShoppingList.Enabled := aEnabled;
  ButtonDeleteShopping.Enabled := aEnabled;
  EditTotalPurchaseAmount.Enabled := aEnabled;
  if (not aEnabled) then
  begin
    DateTimePickerShoppingFrom.Time := Time;
    DateTimePickerShoppingTo.Time := Time;
    EditShop.Text := '';
    RichEditShoppingList.Text := '';
    EditTotalPurchaseAmount.Text := '0';
  end;
end;

procedure TmainForm.EnableTaskElements(const aEnabled: Boolean);
begin
  DateTimePickerTaskFrom.Enabled := aEnabled;
  DateTimePickerTaskTo.Enabled := aEnabled;
  EditTask.Enabled := aEnabled;
  RichEditNotes.Enabled := aEnabled;
  ButtonDeleteTask.Enabled := aEnabled;
  if (not aEnabled) then
  begin
    DateTimePickerTaskFrom.Time := Time;
    DateTimePickerTaskTo.Time := Time;
    EditTask.Text := '';
    RichEditNotes.Text := '';
  end;
end;

procedure TmainForm.FillListViewConversations;
var
  a_Conversation: TConversation;
  a_ListItem: TListItem;
  a_Time1, a_Time2: TTime;
  a_Stunden: Word;
  a_Minuten: Word;
  a_Sekunden: Word;
  a_Milisekunden: Word;
begin
  ListViewConversations.Items.Clear;
  fDay.Conversations.Sort(TComparer<TConversation>.Construct(
        function (const Left, Right: TConversation): Integer
        begin
          DecodeTime(Left.FromTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
          a_Time1 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
          DecodeTime(Right.FromTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
          a_Time2 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
          Result := CompareTime(a_Time1, a_Time2);
          if (Result = 0) then
          begin
            DecodeTime(Left.ToTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
            a_Time1 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
            DecodeTime(Right.ToTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
            a_Time2 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
            Result := CompareTime(a_Time1, a_Time2);
            if (Result = 0) then
              if ( Left.Title > Right.Title ) then
                Result := 1
              else
              if ( Left.Title < Right.Title ) then
                Result := -1
              else
                Result := 0;
          end;
        end
      )
  );
  for a_Conversation in fDay.Conversations do
  begin
    a_ListItem := ListViewConversations.Items.Add;
    a_ListItem.Caption := TimeToStr(a_Conversation.FromTime);
    a_ListItem.SubItems.Add(TimeToStr(a_Conversation.ToTime));
    a_ListItem.SubItems.Add(a_Conversation.Title);
    a_ListItem.Data := a_Conversation;
  end;
end;

procedure TmainForm.FillListViewShoppings;
var
  a_Amount: Double;
  a_Shopping: TShopping;
  a_ListItem: TListItem;
  a_Time1, a_Time2: TTime;
  a_Stunden: Word;
  a_Minuten: Word;
  a_Sekunden: Word;
  a_Milisekunden: Word;
begin
  ListViewShoppings.Items.Clear;
  fDay.Shoppings.Sort(TComparer<TShopping>.Construct(
        function (const Left, Right: TShopping): Integer
        begin
          DecodeTime(Left.FromTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
          a_Time1 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
          DecodeTime(Right.FromTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
          a_Time2 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
          Result := CompareTime(a_Time1, a_Time2);
          if (Result = 0) then
          begin
            DecodeTime(Left.ToTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
            a_Time1 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
            DecodeTime(Right.ToTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
            a_Time2 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
            Result := CompareTime(a_Time1, a_Time2);
            if (Result = 0) then
              if ( Left.Shop > Right.Shop ) then
                Result := 1
              else
              if ( Left.Shop < Right.Shop ) then
                Result := -1
              else
                if ( Left.TotalPurchaseAmount > Right.TotalPurchaseAmount ) then
                  Result := 1
                else
                if ( Left.TotalPurchaseAmount < Right.TotalPurchaseAmount ) then
                  Result := -1
                else
                  Result := 0;
          end;
        end
      )
  );
  a_Amount := 0;
  for a_Shopping in fDay.Shoppings do
  begin
    a_ListItem := ListViewShoppings.Items.Add;
    a_ListItem.Caption := TimeToStr(a_Shopping.FromTime);
    a_ListItem.SubItems.Add(TimeToStr(a_Shopping.ToTime));
    a_ListItem.SubItems.Add(a_Shopping.Shop);
    a_ListItem.SubItems.Add(FloatToStr(a_Shopping.TotalPurchaseAmount));
    a_Amount := a_Amount + a_Shopping.TotalPurchaseAmount;
    a_ListItem.Data := a_Shopping;
  end;
  LabelTotalAmountOfPurchaes2.Caption := FloatToStr(a_Amount);
end;

procedure TmainForm.FillListViewTasks;
var
  a_Task: TTask;
  a_ListItem: TListItem;
  a_Time1, a_Time2: TTime;
  a_Stunden: Word;
  a_Minuten: Word;
  a_Sekunden: Word;
  a_Milisekunden: Word;
begin
  ListViewTasks.Items.Clear;
  fDay.Tasks.Sort(TComparer<TTask>.Construct(
        function (const Left, Right: TTask): Integer
        begin
          DecodeTime(Left.FromTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
          a_Time1 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
          DecodeTime(Right.FromTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
          a_Time2 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
          Result := CompareTime(a_Time1, a_Time2);
          if (Result = 0) then
          begin
            DecodeTime(Left.ToTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
            a_Time1 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
            DecodeTime(Right.ToTime, a_Stunden, a_Minuten, a_Sekunden, a_Milisekunden);
            a_Time2 := EncodeTime(a_Stunden, a_Minuten, a_Sekunden, 0);
            Result := CompareTime(a_Time1, a_Time2);
            if (Result = 0) then
              if ( Left.Task > Right.Task ) then
                Result := 1
              else
              if ( Left.Task < Right.Task ) then
                Result := -1
              else
                Result := 0;
          end;
        end
      )
  );
  for a_Task in fDay.Tasks do
  begin
    a_ListItem := ListViewTasks.Items.Add;
    a_ListItem.Caption := TimeToStr(a_Task.FromTime);
    a_ListItem.SubItems.Add(TimeToStr(a_Task.ToTime));
    a_ListItem.SubItems.Add(a_Task.Task);
    a_ListItem.Data := a_Task;
  end;
end;

procedure TmainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Ask(Sender);
  if (Assigned(fDiary)) then
    FreeAndNil(fDiary);
  if (fFilename <> '') then
  begin
    TSDFileUtils.WriteLastFilenameIntoRegistry(fFilename, 'Software\svens.tools\svensDiary');
    TSDFileUtils.WriteRecentFilesIntoRegistry('Software\svens.tools\svensDiary');
  end;
end;

procedure TmainForm.FormCreate(Sender: TObject);
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    fFilename := TSDFileUtils.ReadLastFilenameFromRegistry('Software\svens.tools\svensDiary');
    TSDFileUtils.ReadRecentFilesFromRegistry('Software\svens.tools\svensDiary');
    if (not FileExists(fFilename)) then
      fFilename := '';
    if (fFilename = '') then
    begin
      OpenNewFile;
    end
    else
    if ( Open =  False ) then
    begin
      ShowMessage('File ' + fFilename + ' can not be opened! A new file will be opened!');
      OpenNewFile;
    end;
    PageControlAll.ActivePageIndex := 0;
    PageControlHealth.ActivePageIndex := 0;
    PageControlWeather.ActivePageIndex := 0;
    DialogUpdated := False;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.GetData;
var
  a_Days: array[1..7] of string;
  a_MemoryStream: TMemoryStream;
begin
  a_Days[1] := 'Sunday';
  a_Days[2] := 'Monday';
  a_Days[3] := 'Tuesday';
  a_Days[4] := 'Wednesday';
  a_Days[5] := 'Thursday';
  a_Days[6] := 'Friday';
  a_Days[7] := 'Saturday';
  LabelDayOfWeek.Caption := a_Days[DayOfWeek(fDay.Date)];
  RichEditWhatHappenedAdditionalyToTheTasks.Text := fDay.WhatHappenedAdditionalyToTheTasks;
  RichEditBreakfast.Text := fDay.Breakfast;
  RichEditLunch.Text := fDay.Lunch;
  RichEditBrunch.Text := fDay.Brunch;
  RichEditTeeCoffeeTime.Text := fDay.TeeCoffeeTime;
  RichEditDinner.Text := fDay.Dinner;
  EditTemperature1.Text := FloatToStr(fDay.TemperatureAtMorning);
  EditPuls1.Text := FloatToStr(fDay.PulseAtMorning);
  CheckBoxHeartArrhythmiaSymbolAppears1.Checked := fDay.HeartArrhythmiaSymbolAppearsAtMorning;
  EditBloodPressureSys1.Text := FloatToStr(fDay.BloodPressureSysAtMorning);
  EditBloodPressureDia1.Text := FloatToStr(fDay.BloodPressureDiaAtMorning);
  EditOxygenSaturation1.Text := FloatToStr(fDay.OxygenSaturationAtMorning);
  EditGlucoseLevel1.Text := FloatToStr(fDay.GlucoseLevelAtMorning);
  EditWeight1.Text := FloatToStr(fDay.WeightAtMorning);
  EditTemperature2.Text := FloatToStr(fDay.TemperatureAtLunch);
  EditPuls2.Text := FloatToStr(fDay.PulseAtLunch);
  CheckBoxHeartArrhythmiaSymbolAppears2.Checked := fDay.HeartArrhythmiaSymbolAppearsAtLunch;
  EditBloodPressureSys2.Text := FloatToStr(fDay.BloodPressureSysAtLunch);
  EditBloodPressureDia2.Text := FloatToStr(fDay.BloodPressureDiaAtLunch);
  EditOxygenSaturation2.Text := FloatToStr(fDay.OxygenSaturationAtLunch);
  EditGlucoseLevel2.Text := FloatToStr(fDay.GlucoseLevelAtLunch);
  EditWeight2.Text := FloatToStr(fDay.WeightAtLunch);
  EditTemperature3.Text := FloatToStr(fDay.TemperatureAtEvening);
  EditPuls3.Text := FloatToStr(fDay.PulseAtEvening);
  CheckBoxHeartArrhythmiaSymbolAppears3.Checked := fDay.HeartArrhythmiaSymbolAppearsAtEvening;
  EditBloodPressureSys3.Text := FloatToStr(fDay.BloodPressureSysAtEvening);
  EditBloodPressureDia3.Text := FloatToStr(fDay.BloodPressureDiaAtEvening);
  EditOxygenSaturation3.Text := FloatToStr(fDay.OxygenSaturationAtEvening);
  EditGlucoseLevel3.Text := FloatToStr(fDay.GlucoseLevelAtEvening);
  EditWeight3.Text := FloatToStr(fDay.WeightAtEvening);
  RichEditlHealthCondition.Text := fDay.HealthCondition;
  EditWeatherHumidity.Text := IntToStr(fDay.WeatherHumidity);
  ComboBoxWeatherMoonPhase.Text := fDay.WeatherMoonPhase;
  EditWeatherPressure.Text := FloatToStr(fDay.WeatherPressure);
  EditWeatherTemperatureAfternoon.Text := IntToStr(fDay.WeatherTemperatureAfternoon);
  EditWeatherTemperatureEvening.Text := IntToStr(fDay.WeatherTemperatureEvening);
  EditWeatherTemperatureMorning.Text := IntToStr(fDay.WeatherTemperatureMorning);
  EditWeatherTemperatureOvernight.Text := IntToStr(fDay.WeatherTemperatureOvernight);
  EditWeatherUVIndex.Text := IntToStr(fDay.WeatherUVIndex);
  ComboBoxWeatherWindDirection.Text := fDay.WeatherWindDirection;
  EditWeatherWindSpeed.Text := IntToStr(fDay.WeatherWindSpeed);
  RichEditWeatherToday.Text := fDay.Weather;
  RichEditThoughts.Text := fDay.Thoughts;
  if (Length(fDay.Picture) > 0) then
  begin
    a_MemoryStream := TMemoryStream.Create;
    try
      a_MemoryStream.WriteBuffer(fDay.Picture[0], Length(fDay.Picture));
      a_MemoryStream.Position := 0;
      ImageOfTheDay.Picture.LoadFromStream(a_MemoryStream);
    finally
      a_MemoryStream.Clear;
      FreeAndNil(a_MemoryStream);
    end;
  end
  else
  begin
    ImageOfTheDay.Picture.Assign(nil);
    SetLength(fBytes, 0);
  end;
  if (fDay.Tasks.Count > 0) then
  begin
    fTask := fDay.Tasks.Items[0];
    GetDataTask;
    EnableTaskElements(True);
  end
  else
  begin
    fTask := nil;
    EnableTaskElements(False);
  end;
  FillListViewTasks;
  if (Assigned(fTask)) then
    SelectItemInListViewTasks;
  if (fDay.Conversations.Count > 0) then
  begin
    fConversation := fDay.Conversations.Items[0];
    GetDataConversation;
    EnableConversationElements(True);
  end
  else
  begin
    fConversation := nil;
    EnableConversationElements(False);
  end;
  FillListViewConversations;
  if (Assigned(fConversation)) then
    SelectItemInListViewConversations;
   if (fDay.Shoppings.Count > 0) then
  begin
    fShopping := fDay.Shoppings.Items[0];
    GetDataShopping;
    EnableShoppingElements(True);
  end
  else
  begin
    fShopping := nil;
    EnableShoppingElements(False);
  end;
  FillListViewShoppings;
  if (Assigned(fShopping)) then
    SelectItemInListViewShoppings;
  UpdateHealthChart;
  UpdateWeatherChart;
end;

procedure TmainForm.GetDataTask;
begin
  DateTimePickerTaskFrom.Time := fTask.FromTime;
  DateTimePickerTaskTo.Time :=  fTask.ToTime;
  EditTask.Text := fTask.Task;
  RichEditNotes.Text := fTask.Notes;
end;

procedure TmainForm.GetDataConversation;
begin
  DateTimePickerFrom.Time := fConversation.FromTime;
  DateTimePickerTo.Time :=  fConversation.ToTime;
  EditConversationTitle.Text := fConversation.Title;
  RichEditConversation.Text := fConversation.Conversation;
end;

procedure TmainForm.GetDataShopping;
begin
  DateTimePickerShoppingFrom.Time := fShopping.FromTime;
  DateTimePickerShoppingTo.Time :=  fShopping.ToTime;
  EditShop.Text := fShopping.Shop;
  RichEditShoppingList.Text := fShopping.ShoppingList;
  EditTotalPurchaseAmount.Text := FloatToStr(fShopping.TotalPurchaseAmount);
end;

function TmainForm.GetDialogUpdated: Boolean;
begin
  Result := fDialogUpdated;
end;

procedure TmainForm.ListViewConversationsClick(Sender: TObject);
var
  a_Conversation: TConversation;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    if (Assigned(ListViewConversations.Selected)) then
    begin
      SetDataConversation;
      a_Conversation := ListViewConversations.Selected.Data;
      if (fConversation.ID <> a_Conversation.ID) then
      begin
        fConversation := ListViewConversations.Selected.Data;
        GetDataConversation;
      end;
    end;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ListViewShoppingsClick(Sender: TObject);
var
  a_Shopping: TShopping;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    if (Assigned(ListViewShoppings.Selected)) then
    begin
      SetDataShopping;
      a_Shopping := ListViewShoppings.Selected.Data;
      if (fShopping.ID <> a_Shopping.ID) then
      begin
        fShopping := ListViewShoppings.Selected.Data;
        GetDataShopping;
      end;
    end;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.ListViewTasksClick(Sender: TObject);
var
  a_Task: TTask;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    if (Assigned(ListViewTasks.Selected)) then
    begin
      SetDataTask;
      a_Task := ListViewTasks.Selected.Data;
      if (fTask.ID <> a_Task.ID) then
      begin
        fTask := ListViewTasks.Selected.Data;
        GetDataTask;
      end;
    end;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

function TmainForm.NotEmptyDayFound(const aDay: TDay): Boolean;
begin
  Result :=
          (aDay.WhatHappenedAdditionalyToTheTasks <> '') or
          (aDay.Breakfast <> '') or
          (aDay.Lunch <> '') or
          (aDay.Brunch <> '') or
          (aDay.TeeCoffeeTime <> '') or
          (aDay.Dinner <> '') or
          (aDay.TemperatureAtMorning <> 0) or
          (aDay.PulseAtMorning <> 0) or
          (aDay.HeartArrhythmiaSymbolAppearsAtMorning = True ) or
          (aDay.BloodPressureSysAtMorning <> 0) or
          (aDay.BloodPressureDiaAtMorning <> 0) or
          (aDay.OxygenSaturationAtMorning <> 0) or
          (aDay.GlucoseLevelAtMorning <> 0) or
          (aDay.WeightAtMorning <> 0) or
          (aDay.TemperatureAtLunch <> 0) or
          (aDay.PulseAtLunch <> 0) or
          (aDay.HeartArrhythmiaSymbolAppearsAtLunch = True) or
          (aDay.BloodPressureSysAtLunch <> 0) or
          (aDay.BloodPressureDiaAtLunch <> 0) or
          (aDay.OxygenSaturationAtLunch <> 0) or
          (aDay.GlucoseLevelAtLunch <> 0) or
          (aDay.WeightAtLunch <> 0) or
          (aDay.TemperatureAtEvening <> 0) or
          (aDay.PulseAtEvening <> 0) or
          (aDay.HeartArrhythmiaSymbolAppearsAtEvening = True) or
          (aDay.BloodPressureSysAtEvening <> 0) or
          (aDay.BloodPressureDiaAtEvening <> 0) or
          (aDay.OxygenSaturationAtEvening <> 0) or
          (aDay.GlucoseLevelAtEvening <> 0) or
          (aDay.WeightAtEvening <> 0) or
          (aDay.HealthCondition <> '') or
          (aDay.WeatherHumidity <> 0) or
          (aDay.WeatherMoonPhase <> '') or
          (aDay.WeatherPressure <> 0) or
          (aDay.WeatherTemperatureAfternoon <> 0) or
          (aDay.WeatherTemperatureEvening <> 0) or
          (aDay.WeatherTemperatureMorning <> 0) or
          (aDay.WeatherTemperatureOvernight <> 0) or
          (aDay.WeatherUVIndex <> 0) or
          (aDay.WeatherWindDirection <> '') or
          (aDay.WeatherWindSpeed <> 0) or
          (aDay.Weather <> '') or
          (aDay.Thoughts <> '') or
          (Length(aDay.Picture) <> 0);
  if (not Result) then
    Result := (aDay.Tasks.Count > 0);
  if (not Result) then
    Result := (aDay.Conversations.Count > 0);
  if (not Result) then
    Result := (aDay.Shoppings.Count > 0);
end;

procedure TmainForm.MenuItemAboutClick(Sender: TObject);
var
  a_About: TFormAbout;
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    a_About := TFormAbout.Create(Self);
    try
      a_About.ShowModal;
    finally
      a_About.Free;
    end;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.MenuItemExitClick(Sender: TObject);
begin
  Close;
end;

procedure TmainForm.MenuItemExporthealthvaluesoftheselectedmonthasaCSVfile1Click(
  Sender: TObject);
var
  i: Int64;
  a_Day: TDay;
  a_HeartArrhythmiaSymbolAppearsAtMorning: String;
  a_HeartArrhythmiaSymbolAppearsAtLunch: String;
  a_HeartArrhythmiaSymbolAppearsAtEvening: String;
  a_FileName: String;
  a_ListOfFilteredDays: TObjectList<TDay>;
  a_Writer: TStreamWriter;
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    CatchEmptyNumberFieldsOnExit(Sender);
    SaveDialog1.FileName :=
      TSDDateUtils.ToYearMonthStr(DateTimePicker1.DateTime) + '-' +
      'HealthValues.csv';
    SaveDialog1.InitialDir := ExtractFilePath(fFileName);
    SaveDialog1.Options := SaveDialog1.Options + [ofOverwritePrompt];
    SaveDialog1.DefaultExt := 'csv';   
    SaveDialog1.Filter := 'CSV- Files (*.csv)|*.csv';
    SaveDialog1.FilterIndex := 1;
    if (SaveDialog1.Execute) then
    begin
      Screen.Cursor := crHourGlass;
      try
        a_ListOfFilteredDays := TObjectList<TDay>.Create;
        a_ListOfFilteredDays.OwnsObjects := False;
        try
          SearchActualMonth(a_ListOfFilteredDays, YearOf(DateTimePicker1.DateTime), MonthOf(DateTimePicker1.DateTime));
          a_FileName := SaveDialog1.FileName;
          if (Pos('.csv', a_FileName, 1) = 0) then
            a_FileName := a_FileName + '.csv';
          a_Writer := TStreamWriter.Create(a_FileName, false, TEncoding.UTF8);
          try
            a_Writer.WriteLine('Date;'+
                               'Morning;' +
                               'Temperature;' +
                               'Puls;' +
                               'Heart Arrhythmia Symbol Appears;' +
                               'Blood Pressure Sys;' +
                               'Blood Pressure Dia;' +
                               'Oxygen Saturation;' +
                               'Glucose Level;' +
                               'Weight;' +
                               'Afternoon;' +
                               'Temperature;' +
                               'Puls;' +
                               'Heart Arrhythmia Symbol Appears;' +
                               'Blood Pressure Sys;' +
                               'Blood Pressure Dia;' +
                               'Oxygen Saturation;' +
                               'Glucose Level;' +
                               'Weight;' +
                               'Evening;' +
                               'Temperature;' +
                               'Puls;' +
                               'Heart Arrhythmia Symbol Appears;' +
                               'Blood Pressure Sys;' +
                               'Blood Pressure Dia;' +
                               'Oxygen Saturation;' +
                               'Glucose Level;' +
                               'Weight;');
            for i := 0 to a_ListOfFilteredDays.Count - 1 do
            begin
              a_Day := a_ListOfFilteredDays.Items[i];
              if (a_Day.HeartArrhythmiaSymbolAppearsAtMorning) then
                a_HeartArrhythmiaSymbolAppearsAtMorning := 'Yes'
              else
                a_HeartArrhythmiaSymbolAppearsAtMorning := 'No';
              if (a_Day.HeartArrhythmiaSymbolAppearsAtLunch) then
                a_HeartArrhythmiaSymbolAppearsAtLunch := 'Yes'
              else
                a_HeartArrhythmiaSymbolAppearsAtLunch := 'No';
              if (a_Day.HeartArrhythmiaSymbolAppearsAtEvening) then
                a_HeartArrhythmiaSymbolAppearsAtEvening := 'Yes'
              else
                a_HeartArrhythmiaSymbolAppearsAtEvening := 'No';
              a_Writer.WriteLine(TSDDateUtils.ToYearMonthDayStr(a_Day.Date) + ';' +
                                 'Morning;' +
                                 FloatToStr(a_Day.TemperatureAtMorning) + ';' +
                                 FloatToStr(a_Day.PulseAtMorning) + ';' +
                                 a_HeartArrhythmiaSymbolAppearsAtMorning + ';' +
                                 FloatToStr(a_Day.BloodPressureSysAtMorning) + ';' +
                                 FloatToStr(a_Day.BloodPressureDiaAtMorning) + ';' +
                                 FloatToStr(a_Day.OxygenSaturationAtMorning) + ';' +
                                 FloatToStr(a_Day.GlucoseLevelAtMorning) + ';' +
                                 FloatToStr(a_Day.WeightAtMorning) + ';' +
                                 'Afternoon;' +
                                 FloatToStr(a_Day.TemperatureAtLunch) + ';' +
                                 FloatToStr(a_Day.PulseAtLunch) + ';' +
                                 a_HeartArrhythmiaSymbolAppearsAtLunch + ';' +
                                 FloatToStr(a_Day.BloodPressureSysAtLunch) + ';' +
                                 FloatToStr(a_Day.BloodPressureDiaAtLunch) + ';' +
                                 FloatToStr(a_Day.OxygenSaturationAtLunch) + ';' +
                                 FloatToStr(a_Day.GlucoseLevelAtLunch) + ';' +
                                 FloatToStr(a_Day.WeightAtLunch) + ';' +
                                 'Evening;' +
                                 FloatToStr(a_Day.TemperatureAtEvening) + ';' +
                                 FloatToStr(a_Day.PulseAtEvening) + ';' +
                                 a_HeartArrhythmiaSymbolAppearsAtEvening + ';' +
                                 FloatToStr(a_Day.BloodPressureSysAtEvening) + ';' +
                                 FloatToStr(a_Day.BloodPressureDiaAtEvening) + ';' +
                                 FloatToStr(a_Day.OxygenSaturationAtEvening) + ';' +
                                 FloatToStr(a_Day.GlucoseLevelAtEvening) + ';' +
                                 FloatToStr(a_Day.WeightAtEvening));
            end;
          finally
            a_Writer.Free;
          end;
        finally
          a_ListOfFilteredDays.Free;
        end;
      finally
        Screen.Cursor := crDefault;
      end;
    end;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.MenuItemExportSelectedMonthAsTextfileClick(Sender: TObject);
var
  i: Int64;
  a_Conversation: TConversation;
  a_Day: TDay;
  a_FileName: String;
  a_ListOfFilteredDays: TObjectList<TDay>;
  a_Shopping: TShopping;
  a_Task: TTask;
  a_Writer: TStreamWriter;
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    CatchEmptyNumberFieldsOnExit(Sender);
    SaveDialog1.FileName :=
      TSDDateUtils.ToYearMonthStr(DateTimePicker1.DateTime) + '-' +
      'Diary.txt';
    SaveDialog1.InitialDir := ExtractFilePath(fFileName);
    SaveDialog1.Options := SaveDialog1.Options + [ofOverwritePrompt];
    SaveDialog1.DefaultExt := 'txt';   
    SaveDialog1.Filter := 'Text- Files (*.txt)|*.txt';
    SaveDialog1.FilterIndex := 1;
    if (SaveDialog1.Execute) then
    begin
      Screen.Cursor := crHourGlass;
      try
        a_ListOfFilteredDays := TObjectList<TDay>.Create;
        a_ListOfFilteredDays.OwnsObjects := False;
        try
          SearchActualMonth(a_ListOfFilteredDays, YearOf(DateTimePicker1.DateTime),  MonthOf(DateTimePicker1.DateTime));
          a_FileName := SaveDialog1.FileName;
          if (Pos('.txt', a_FileName, 1) = 0) then
            a_FileName := a_FileName + '.txt';
          a_Writer := TStreamWriter.Create(a_FileName, false, TEncoding.UTF8);
          try
            for i := 0 to a_ListOfFilteredDays.Count - 1 do
            begin
              a_Day := a_ListOfFilteredDays.Items[i];
              a_Writer.WriteLine('------------------------------------------------------------------------------------------');
              a_Writer.WriteLine(TSDDateUtils.ToYearMonthDayWeekdayStr(a_Day.Date));
              a_Writer.WriteLine('------------------------------------------------------------------------------------------');
              a_Writer.WriteLine('Tasks');
              a_Writer.WriteLine('---------------------------------------');
              if (a_Day.Tasks.Count > 0) then
                for a_Task in a_Day.Tasks do
                begin
                  a_Writer.WriteLine(TimeToStr(a_Task.FromTime) + ' ' + TimeToStr(a_Task.ToTime) + ' ' + a_Task.Task);
                  if (a_Task.Notes <> '') then
                    a_Writer.WriteLine(a_Task.Notes);
                end;
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('What else happened besides the tasks');
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine(a_Day.WhatHappenedAdditionalyToTheTasks);
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Conversations');
              a_Writer.WriteLine('---------------------------------------');
              if (a_Day.Conversations.Count > 0) then
                for a_Conversation in a_Day.Conversations do
                begin
                  a_Writer.WriteLine(TimeToStr(a_Conversation.FromTime) + ' ' + TimeToStr(a_Conversation.ToTime) + ' ' + a_Conversation.Title);
                  if (a_Conversation.Conversation <> '') then
                    a_Writer.WriteLine(a_Conversation.Conversation);
                end;
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Shopping');
              a_Writer.WriteLine('---------------------------------------');
              if (a_Day.Shoppings.Count > 0) then
                for a_Shopping in a_Day.Shoppings do
                begin
                  a_Writer.WriteLine(TimeToStr(a_Shopping.FromTime) + ' ' + TimeToStr(a_Shopping.ToTime) + ' ' + a_Shopping.Shop);
                  if (a_Shopping.ShoppingList <> '') then
                    a_Writer.WriteLine(a_Shopping.ShoppingList);
                  a_Writer.WriteLine( 'Total Purchase Amount: ' + FloatToStr(a_Shopping.TotalPurchaseAmount));
                end;
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Meals');
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Breakfast:');
              a_Writer.WriteLine(a_Day.Breakfast);
              a_Writer.WriteLine('Lunch:');
              a_Writer.WriteLine(a_Day.Lunch);
              a_Writer.WriteLine('Brunch:');
              a_Writer.WriteLine(a_Day.Brunch);
              a_Writer.WriteLine('Tee Coffee Time:');
              a_Writer.WriteLine(a_Day.TeeCoffeeTime);
              a_Writer.WriteLine('Dinner:');
              a_Writer.WriteLine(a_Day.Dinner);
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Health');
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Morning');
              a_Writer.WriteLine('Temperature: ' + FloatToStr(a_Day.TemperatureAtMorning));
              a_Writer.WriteLine('Puls: ' +  FloatToStr(a_Day.PulseAtMorning));
              if (a_Day.HeartArrhythmiaSymbolAppearsAtMorning) then
                a_Writer.WriteLine('Heart arrhythmia symbol appears: Yes')
              else
                a_Writer.WriteLine('Heart arrhythmia symbol appears: No');
              a_Writer.WriteLine('Blood pressure Sys: ' + FloatToStr(a_Day.BloodPressureSysAtMorning));
              a_Writer.WriteLine('Blood pressure Dia: ' + FloatToStr(a_Day.BloodPressureDiaAtMorning));
              a_Writer.WriteLine('Oxygen saturation: ' + FloatToStr(a_Day.OxygenSaturationAtMorning));
              a_Writer.WriteLine('Glucose level: ' + FloatToStr(a_Day.GlucoseLevelAtMorning));
              a_Writer.WriteLine('Weight: ' + FloatToStr(a_Day.WeightAtMorning));
              a_Writer.WriteLine('Afternoon');
              a_Writer.WriteLine('Temperature: ' + FloatToStr(a_Day.TemperatureAtLunch));
              a_Writer.WriteLine('Puls: ' + FloatToStr(a_Day.PulseAtLunch));
              if (a_Day.HeartArrhythmiaSymbolAppearsAtLunch) then
                a_Writer.WriteLine('Heart arrhythmia symbol appears: Yes')
              else
                a_Writer.WriteLine('Heart arrhythmia symbol appears: No');
              a_Writer.WriteLine('Blood pressure Sys: ' + FloatToStr(a_Day.BloodPressureSysAtLunch));
              a_Writer.WriteLine('Blood pressure Dia: ' + FloatToStr(a_Day.BloodPressureDiaAtLunch));
              a_Writer.WriteLine('Oxygen saturation: ' + FloatToStr(a_Day.OxygenSaturationAtLunch));
              a_Writer.WriteLine('Glucose level: ' + FloatToStr(a_Day.GlucoseLevelAtLunch));
              a_Writer.WriteLine('Weight: ' + FloatToStr(a_Day.WeightAtLunch));
              a_Writer.WriteLine('Evening');
              a_Writer.WriteLine('Temperature: ' + FloatToStr(a_Day.TemperatureAtEvening));
              a_Writer.WriteLine('Puls: ' + FloatToStr(a_Day.PulseAtEvening));
              if (a_Day.HeartArrhythmiaSymbolAppearsAtEvening) then
                a_Writer.WriteLine('Heart arrhythmia symbol appears: Yes')
              else
                a_Writer.WriteLine('Heart arrhythmia symbol appears: No');
              a_Writer.WriteLine('Blood pressure Sys: ' + FloatToStr(a_Day.BloodPressureSysAtEvening));
              a_Writer.WriteLine('Blood pressure Dia: ' + FloatToStr(a_Day.BloodPressureDiaAtEvening));
              a_Writer.WriteLine('Oxygen saturation: ' + FloatToStr(a_Day.OxygenSaturationAtEvening));
              a_Writer.WriteLine('Glucose level: ' + FloatToStr(a_Day.GlucoseLevelAtEvening));
              a_Writer.WriteLine('Weight: ' + FloatToStr(a_Day.WeightAtEvening));
              a_Writer.WriteLine('Health condition:');
              a_Writer.WriteLine(a_Day.HealthCondition);
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Weather Today');
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Temperature at morning: ' + IntToStr(a_Day.WeatherTemperatureMorning));
              a_Writer.WriteLine('Temperature at afternoon: ' + IntToStr(a_Day.WeatherTemperatureAfternoon));
              a_Writer.WriteLine('Temperature at evening: ' + IntToStr(a_Day.WeatherTemperatureEvening));
              a_Writer.WriteLine('Temperature at overnight: ' + IntToStr(a_Day.WeatherTemperatureOvernight));
              a_Writer.WriteLine('Humidity: ' + IntToStr(a_Day.WeatherHumidity));
              a_Writer.WriteLine('Pressure: ' + FloatToStr(a_Day.WeatherPressure));
              a_Writer.WriteLine('Wind direction: ' + a_Day.WeatherWindDirection);
              a_Writer.WriteLine('Wind speed: '  + IntToStr(a_Day.WeatherWindSpeed));
              a_Writer.WriteLine('UVIndex: ' + IntToStr(a_Day.WeatherUVIndex));
              a_Writer.WriteLine('Moon phase: ' + a_Day.WeatherMoonPhase);
              a_Writer.WriteLine('Weather condition:');
              a_Writer.WriteLine(a_Day.Weather);
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine('Thoughts');
              a_Writer.WriteLine('---------------------------------------');
              a_Writer.WriteLine(a_Day.Thoughts);
              a_Writer.WriteLine();
            end;
          finally
            a_Writer.Free;
          end;
        finally
          a_ListOfFilteredDays.Free;
        end;
      finally
        Screen.Cursor := crDefault;
      end;
    end;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.MenuItemImportTasksFromACSVFileClick(Sender: TObject);
var
  i: Int64;
  a_Day: TDay;
  a_FileName: String;
  a_FirstLine: Boolean;
  a_IgnoreStartDateTime: Boolean;
  a_Line: String;
  a_Pos, a_Pos2: Integer;
  a_Reader: TStreamReader;
  a_Result: Boolean;
  a_Str: String;
  a_StrDay: String;
  a_StrHours: String;
  a_StrMiliseconds: String;
  a_StrMinutes: String;
  a_StrMonth: String;
  a_StrSeconds: String;
  a_StrTask: String;
  a_StrYear: String;
  a_FirstTask, a_TaskOfTheDay: TTaskOfTheDay;
  a_TasksOfTheDay: TObjectList<TTaskOfTheDay>;
  a_EndDateTime: TDateTime;
  a_StartDateTime: TDateTime;
  a_Task: TTask;

  function ReadDateTime: Boolean;
  begin
    Result := True;
    a_Pos := Pos(';', a_Line);
    a_Str := Copy(a_Line, 0, a_Pos-1);
    a_Pos2 := Pos('-', a_Str);
    a_StrYear := Copy(a_Str, 0, a_Pos2-1);
    if (a_StrYear = '') then
      Exit(False);
    a_Str := Copy(a_Str, a_Pos2+1, Length(a_Str));
    a_Pos2 := Pos('-', a_Str);
    a_StrMonth := Copy(a_Str, 0, a_Pos2-1);
    a_Str := Copy(a_Str, a_Pos2+1, Length(a_Str));
    a_Pos2 := Pos(' ', a_Str);
    a_StrDay := Copy(a_Str, 0, a_Pos2-1);
    a_Str := Copy(a_Str, a_Pos2+1, Length(a_Str));
    a_Pos2 := Pos(':', a_Str);
    a_StrHours := Copy(a_Str, 0, a_Pos2-1);
    a_Str := Copy(a_Str, a_Pos2+1, Length(a_Str));
    a_Pos2 := Pos(':', a_Str);
    a_StrMinutes := Copy(a_Str, 0, a_Pos2-1);
    a_StrSeconds := '00';
    a_StrMiliseconds := '0000';
  end;

begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    Ask(Sender);
    ShowMessage(
      'The CSV file must be structured as follows: ' +
      'Task; Start date and time; End date and time; Note. ' +
      'First line is not read because it is the header!');
    OpenDialog1.Filter := 'CSV- Files (*.csv)|*.csv';
    if (OpenDialog1.Execute) then
    begin
      Screen.Cursor := crHourGlass;
      try
        a_FileName := OpenDialog1.FileName;
        if (FileExists(a_FileName)) then
        begin
          a_IgnoreStartDateTime :=
            ( MessageDlg('Should only the end date time be taken into account ' +
                         'and start date time ignored?',
                         mtConfirmation,
                         [mbYes, mbNo],
                         0,
                         mbYes) = mrYes );
          a_TasksOfTheDay := TObjectList<TTaskOfTheDay>.Create;
          try
            a_Reader := TStreamReader.Create(a_FileName, TEncoding.UTF8);
            try
              a_EndDateTime := Now;
              a_StartDateTime := Now;
              a_TaskOfTheDay := nil;
              a_FirstLine := True;
              while not a_Reader.EndOfStream do
              begin
                a_Line := a_Reader.ReadLine;
                if (not a_FirstLine) then
                begin
                  // Read task
                  a_Pos := Pos(';', a_Line);
                  if (a_Pos <> 0) then
                  begin
                    a_StrTask := Copy(a_Line, 0, a_Pos-1);
                    // Read start datetime
                    a_Line := Copy(a_Line, a_Pos+1, Length(a_Line));
                    a_Result := ReadDateTime;
                    if (a_Result) then
                    begin
                      a_StartDateTime := EncodeDateTime(StrToInt(a_StrYear),
                                                        StrToInt(a_StrMonth),
                                                        StrToInt(a_StrDay),
                                                        StrToInt(a_StrHours),
                                                        StrToInt(a_StrMinutes),
                                                        StrToInt(a_StrSeconds),
                                                        StrToInt(a_StrMiliseconds));
                      // Read end datetime
                      a_Line := Copy(a_Line, a_Pos+1, Length(a_Line));
                      a_Result := ReadDateTime;
                      if (a_Result) then
                        a_EndDateTime := EncodeDateTime(StrToInt(a_StrYear),
                                                        StrToInt(a_StrMonth),
                                                        StrToInt(a_StrDay),
                                                        StrToInt(a_StrHours),
                                                        StrToInt(a_StrMinutes),
                                                        StrToInt(a_StrSeconds),
                                                        StrToInt(a_StrMiliseconds));

                    end;
                    // Read notice
                    if (a_Result) then
                    begin
                      a_Line := Copy(a_Line, a_Pos+1, Length(a_Line));
                      a_TaskOfTheDay := TTaskOfTheDay.Create;
                      a_TaskOfTheDay.StartDateTime := a_StartDateTime;
                      a_TaskOfTheDay.EndDateTime := a_EndDateTime;
                      a_TaskOfTheDay.Task := a_StrTask;
                      a_TaskOfTheDay.Notice := a_Line;
                      a_TasksOfTheDay.Add(a_TaskOfTheDay);
                    end
                    else
                      a_TaskOfTheDay := nil;
                  end
                  else
                    if (Assigned(a_TaskOfTheDay)) and
                       (a_Line <> '') and
                       (a_Line <> sLineBreak) then
                     a_TaskOfTheDay.Notice := a_TaskOfTheDay.Notice + ' ' + a_Line;
                end
                else
                  a_FirstLine := False;
              end;
            finally
              a_Reader.Free;
            end;
            a_TasksOfTheDay.Sort(TComparer<TTaskOfTheDay>.Construct(
              function (const Left, Right: TTaskOfTheDay): Integer
              begin
                Result := CompareDate(Left.StartDateTime, Right.StartDateTime);
                if ( Result = 0 ) then
                  if ( a_IgnoreStartDateTime ) then
                    Result := CompareTime(Left.EndDateTime, Right.EndDateTime)
                  else
                    Result := CompareTime(Left.StartDateTime, Right.StartDateTime);
              end
              )
            );
            if (a_TasksOfTheDay.Count > 0) then
            begin
              a_FirstTask := a_TasksOfTheDay.Items[0];
              a_Day := fDiary.GetDay(a_FirstTask.StartDateTime);
              for i := 0 to a_TasksOfTheDay.Count - 1 do
              begin
                a_TaskOfTheDay := a_TasksOfTheDay.Items[i];
                if (CompareDate(a_FirstTask.StartDateTime, a_TaskOfTheDay.StartDateTime) <> 0) then
                begin
                  a_FirstTask := a_TaskOfTheDay;
                  a_Day := fDiary.GetDay(a_FirstTask.StartDateTime);
                end;
                a_Task := TTask.Create;
                a_Day.LastTaskID := a_Day.LastTaskID + 1;
                a_Task.ID :=  a_Day.LastTaskID;
                if (a_IgnoreStartDateTime) then
                  a_Task.FromTime := a_TaskOfTheDay.EndDateTime.GetTime
                else
                  a_Task.FromTime := a_TaskOfTheDay.StartDateTime.GetTime;
                a_Task.ToTime := a_TaskOfTheDay.EndDateTime.GetTime;
                a_Task.Task := a_TaskOfTheDay.Task;
                a_Task.Notes := a_TaskOfTheDay.Notice;
                a_Day.Tasks.Add(a_Task);
              end;
            end;
          finally
            a_TasksOfTheDay.Free;
            DialogUpdated := True;
            GetData();
          end;
        end
        else
          ShowMessage('File ' + a_FileName + ' does not exist.');
      finally
        Screen.Cursor := crDefault;
      end;
    end;
  finally
    fBusy := False;
  end;

end;

procedure TmainForm.MenuItemNewClick(Sender: TObject);
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    Ask(Sender);
    Screen.Cursor := crHourGlass;
    try
      if (Assigned(fDiary)) then
        FreeAndNil(fDiary);
      OpenNewFile;
    finally
      Screen.Cursor := crDefault;
    end;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.MenuItemOpenFileClick(Sender: TObject);
var
  a_FileName: String;
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    Ask(Sender);
    OpenDialog1.FileName := fFileName;
    OpenDialog1.Filter := 'svensDiary- Files (*.svensDiary)|*.svensDiary';
    if (OpenDialog1.Execute) then
    begin
      a_FileName := OpenDialog1.FileName;
      if (FileExists(a_FileName)) then
      begin
        fFileName := a_FileName;
        if (Assigned(fDiary)) then
          FreeAndNil(fDiary);
        if ( Open =  False ) then
        begin
          ShowMessage('File ' + fFileName + ' can not be opened! A new file will be opened!');
          fFileName := '';
          OpenNewFile;
        end;
      end
      else
        ShowMessage('File ' + a_FileName + ' does not exist.');
    end;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.MenuItemRecentFile1Click(Sender: TObject);
begin
  OpenRecentFile(Sender, TSDFileUtils.RecentFiles[1]);
end;

procedure TmainForm.MenuItemRecentFile2Click(Sender: TObject);
begin
  OpenRecentFile(Sender, TSDFileUtils.RecentFiles[2]);
end;

procedure TmainForm.MenuItemRecentFile3Click(Sender: TObject);
begin
  OpenRecentFile(Sender, TSDFileUtils.RecentFiles[3]);
end;

procedure TmainForm.MenuItemRecentFile4Click(Sender: TObject);
begin
  OpenRecentFile(Sender, TSDFileUtils.RecentFiles[4]);
end;

procedure TmainForm.MenuItemRecentFile5Click(Sender: TObject);
begin
  OpenRecentFile(Sender, TSDFileUtils.RecentFiles[5]);
end;

procedure TmainForm.MenuItemRecentFile6Click(Sender: TObject);
begin
  OpenRecentFile(Sender, TSDFileUtils.RecentFiles[6]);
end;

procedure TmainForm.MenuItemSaveAsClick(Sender: TObject);
var
  a_OldFileName: String;
  a_Year: Word;
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    a_OldFileName := fFileName;
    if (fFileName = '') then
    begin
      a_Year := YearOf(DateTimePicker1.DateTime);
      SaveDialog1.FileName :=
        IntToStr(a_Year) + '-' +
        'Diary.svensDiary';
      SaveDialog1.InitialDir := GetCurrentDir;
    end
    else
    begin
      SaveDialog1.FileName := ExtractFileName(fFileName);
      SaveDialog1.InitialDir := ExtractFilePath(fFileName);
    end;
    SaveDialog1.Options := SaveDialog1.Options + [ofOverwritePrompt];
    SaveDialog1.DefaultExt := 'svensDiary';   
    SaveDialog1.Filter := 'svensDiary- Files (*.svensDiary)|*.svensDiary';
    SaveDialog1.FilterIndex := 1;
    if (SaveDialog1.Execute) then
    begin
      fFileName := SaveDialog1.FileName;
      if (Pos('.svensDiary', fFileName, 1) = 0) then
        fFileName := fFileName + '.svensDiary';
      SecurePicture;
      Save;
      Self.Caption := 'svensDiary: ' + fFileName;
      TSDFileUtils.SaveRecentFile(fFileName);
      UpdateMenuItemsRecentFiles;
    end
    else
      fFileName := a_OldFileName;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.MenuItemSaveClick(Sender: TObject);
begin
  if (fFileName <> '') then
  begin
    if (fBusy = True) then
      Exit;
    fBusy := True;
    try
      SecurePicture;
      Save;
    finally
      fBusy := False;
    end;
  end
  else
    MenuItemSaveAsClick(Sender);
end;

function TmainForm.Open: Boolean;
var
  i,j: Int64;
  a_Conversation: TConversation;
  a_File: TFileStream;
  a_BR: TBinaryReader;
  a_Day: TDay;
  a_Date: TDateTime;
  a_Count, a_Count2: Int64;
  a_PictureLength: Integer;
  a_Shopping: TShopping;
  a_Task: TTask;
begin
  Screen.Cursor := crHourGlass;
  try
    Result := True;
    if (Assigned(fDiary)) then
      FreeAndNil(fDiary);
    fDiary := TDiary.Create;
    try
      a_File := TFileStream.Create(fFileName, fmOpenRead);
      a_BR := TBinaryReader.Create(a_File, TEncoding.Unicode, false);
      try
        fDiary.Version := a_BR.ReadInteger;
        fDiary.Copyright := a_BR.ReadString;
        if (fDiary.Version < 6) then
          a_Count := a_BR.ReadInteger
        else
          a_Count := a_BR.ReadInt64;
        for i := 0 to a_Count - 1 do
        begin
          a_Date := a_BR.ReadDouble;
          a_Day := TDay.Create(a_Date);
          fDiary.DB.Add(a_Day);
          if (fDiary.Version < 10) then
          begin
            a_Task := TTask.Create;
            a_Day.LastTaskID := 1;
            a_Task.ID := a_Day.LastTaskID;
            a_Task.FromTime := EncodeTime(0,0,0,0);
            a_Task.ToTime := EncodeTime(23,59,59,0);
            a_Task.Task := 'Imported Task';
            a_Task.Notes := a_BR.ReadString;
            a_Day.Tasks.Add(a_Task);
          end;
          a_Day.WhatHappenedAdditionalyToTheTasks := a_BR.ReadString;
          a_Day.Breakfast := a_BR.ReadString;
          a_Day.Lunch := a_BR.ReadString;
          if (fDiary.Version >= 8) then
            a_Day.Brunch := a_BR.ReadString;
          if (fDiary.Version >= 7) then
            a_Day.TeeCoffeeTime := a_BR.ReadString;
          a_Day.Dinner := a_BR.ReadString;
          a_Day.TemperatureAtMorning := a_BR.ReadDouble;
          a_Day.PulseAtMorning := a_BR.ReadDouble;
          if (fDiary.Version >= 2) then
            a_Day.HeartArrhythmiaSymbolAppearsAtMorning := a_BR.ReadBoolean;
          a_Day.BloodPressureSysAtMorning := a_BR.ReadDouble;
          a_Day.BloodPressureDiaAtMorning := a_BR.ReadDouble;
          a_Day.OxygenSaturationAtMorning := a_BR.ReadDouble;
          if (fDiary.Version >= 2) then
            a_Day.GlucoseLevelAtMorning := a_BR.ReadDouble;
          a_Day.WeightAtMorning := a_BR.ReadDouble;
          a_Day.TemperatureAtLunch := a_BR.ReadDouble;
          a_Day.PulseAtLunch := a_BR.ReadDouble;
          if (fDiary.Version >= 2) then
            a_Day.HeartArrhythmiaSymbolAppearsAtLunch := a_BR.ReadBoolean;
          a_Day.BloodPressureSysAtLunch := a_BR.ReadDouble;
          a_Day.BloodPressureDiaAtLunch := a_BR.ReadDouble;
          a_Day.OxygenSaturationAtLunch := a_BR.ReadDouble;
          if (fDiary.Version >= 2) then
            a_Day.GlucoseLevelAtLunch := a_BR.ReadDouble;
          a_Day.WeightAtLunch := a_BR.ReadDouble;
          a_Day.TemperatureAtEvening := a_BR.ReadDouble;
          a_Day.PulseAtEvening := a_BR.ReadDouble;
          if (fDiary.Version >= 2) then
            a_Day.HeartArrhythmiaSymbolAppearsAtEvening := a_BR.ReadBoolean;
          a_Day.BloodPressureSysAtEvening := a_BR.ReadDouble;
          a_Day.BloodPressureDiaAtEvening := a_BR.ReadDouble;
          a_Day.OxygenSaturationAtEvening := a_BR.ReadDouble;
          if (fDiary.Version >= 2) then
            a_Day.GlucoseLevelAtEvening := a_BR.ReadDouble;
          a_Day.WeightAtEvening := a_BR.ReadDouble;
          a_Day.HealthCondition := a_BR.ReadString;
          if (fDiary.Version >= 3) then
          begin
            a_Day.WeatherHumidity := a_BR.ReadInteger;
            if (fDiary.Version >= 5) then
            begin
              a_Day.WeatherMoonPhase := a_BR.ReadString;
            end;
            a_Day.WeatherPressure := a_BR.ReadDouble;
            a_Day.WeatherTemperatureAfternoon := a_BR.ReadInteger;
            a_Day.WeatherTemperatureEvening := a_BR.ReadInteger;
            a_Day.WeatherTemperatureMorning := a_BR.ReadInteger;
            a_Day.WeatherTemperatureOvernight := a_BR.ReadInteger;
            a_Day.WeatherUVIndex := a_BR.ReadInteger;
            a_Day.WeatherWindDirection := a_BR.ReadString;
            a_Day.WeatherWindSpeed := a_BR.ReadInteger;
          end;
          a_Day.Weather := a_BR.ReadString;
          a_Day.Thoughts := a_BR.ReadString;
          if (fDiary.Version >= 4) then
          begin
            a_PictureLength := a_BR.ReadInteger;
            a_Day.Picture := a_BR.ReadBytes(a_PictureLength);
          end;
          if (fDiary.Version >= 10) then
          begin
            a_Day.LastTaskID := a_BR.ReadInt64;
            a_Count2 := a_BR.ReadInt64;
            if (a_Count2 > 0) then
              for j := 0 to a_Count2 - 1 do
              begin
                a_Task := TTask.Create;
                a_Task.ID := a_BR.ReadInt64;
                a_Task.FromTime := a_BR.ReadDouble;
                a_Task.ToTime := a_BR.ReadDouble;
                a_Task.Task := a_BR.ReadString;
                a_Task.Notes := a_BR.ReadString;
                a_Day.Tasks.Add(a_Task);
              end;
          end;
          if (fDiary.Version >= 6) then
          begin
            if (fDiary.Version >= 9) then
              a_Day.LastConversationID := a_BR.ReadInt64
            else
              a_Day.LastConversationID := a_BR.ReadInteger;
            a_Count2 := a_BR.ReadInt64;
            if (a_Count2 > 0) then
              for j := 0 to a_Count2 - 1 do
              begin
                a_Conversation := TConversation.Create;
                a_Conversation.ID := a_BR.ReadInt64;
                a_Conversation.FromTime := a_BR.ReadDouble;
                a_Conversation.ToTime := a_BR.ReadDouble;
                a_Conversation.Title := a_BR.ReadString;
                a_Conversation.Conversation := a_BR.ReadString;
                a_Day.Conversations.Add(a_Conversation);
              end;
          end;
          if (fDiary.Version >= 9) then
          begin
            a_Day.LastShoppingID := a_BR.ReadInt64;
            a_Count2 := a_BR.ReadInt64;
            if (a_Count2 > 0) then
              for j := 0 to a_Count2 - 1 do
              begin
                a_Shopping := TShopping.Create;
                a_Shopping.ID := a_BR.ReadInt64;
                a_Shopping.FromTime := a_BR.ReadDouble;
                a_Shopping.ToTime := a_BR.ReadDouble;
                a_Shopping.Shop := a_BR.ReadString;
                a_Shopping.ShoppingList := a_BR.ReadString;
                a_Shopping.TotalPurchaseAmount := a_BR.ReadDouble;
                a_Day.shoppings.Add(a_Shopping);
              end;
          end;
        end;
        a_BR.Close;
      finally
        a_BR.Free;
        a_File.Free;
      end;
    except
      on Exception do
      begin
        Result := False;
      end;
    end;
    if (Result = True) then
    begin
      DialogUpdated := False;
      Self.Caption := 'svensDiary: ' + fFileName;
      TSDFileUtils.SaveRecentFile(fFileName);
      UpdateMenuItemsRecentFiles;
      fDiary.Version := FILE_VERSION;
      fDay := fDiary.GetDay(Now);
      PageControlAll.ActivePageIndex := 0;
      PageControlHealth.TabIndex := 0;
      ComboBoxHealthValue.ItemIndex := 0;
      DateTimePicker1.Date := fDay.Date;
      GetData;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.OpenNewFile;
begin
  Screen.Cursor := crHourGlass;
  try
    fFileName := '';
    DialogUpdated := False;
    Self.Caption := 'svensDiary: NewFile.svensDiary';
    fDiary := TDiary.Create;
    fDay := fDiary.GetDay(Now);
    PageControlAll.ActivePageIndex := 0;
    PageControlHealth.ActivePageIndex := 0;
    PageControlWeather.ActivePageIndex := 0;
    DateTimePicker1.Date := fDay.Date;
    GetData;
  finally
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.OpenRecentFile(Sender: TObject; aFileName: String);
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    Ask(Sender);
    if (FileExists(aFileName)) then
    begin
      fFileName := aFileName;
      if (Assigned(fDiary)) then
        FreeAndNil(fDiary);
      if ( Open =  False ) then
      begin
        ShowMessage('File ' + fFileName + ' can not be opened! A new file will be opened!');
        fFileName := '';
        OpenNewFile;
      end;
    end
    else
    begin
      TSDFileUtils.RemoveRecentFile(aFileName);
      UpdateMenuItemsRecentFiles;
      ShowMessage('File ' + aFilename + ' does not exist.');
    end;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.RadioGroupChartTypeClick(Sender: TObject);
begin
  if (fBusy = True) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    UpdateHealthChart;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.RichEditKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (fBusy = True) then
    Exit;
  fBusy := True;
  try
    TestData;
  finally
    fBusy := False;
  end;
end;

procedure TmainForm.Save;
var
  i: Int64;
  a_Conversation: TConversation;
  a_Day: TDay;
  a_File: TFileStream;
  a_BW: TBinaryWriter;
  a_Length: Integer;
  a_NewFile: Boolean;
  a_Shopping: TShopping;
  a_Task: TTask;
begin
  Screen.Cursor := crHourGlass;
  try
    CatchEmptyNumberFieldsOnExit(nil);
    TSDFileUtils.MakeBackup(fFileName, MAX_BACKUP);
    for i := fDiary.DB.Count - 1 downto 0 do
    begin
      a_Day := fDiary.DB.Items[i];
      if (not NotEmptyDayFound(a_Day)) and (CompareDate(fDay.Date, a_Day.Date) <> 0) then
        fDiary.DB.Delete(i);
    end;
    a_NewFile := not FileExists(fFileName);
    a_File := TFileStream.Create(fFileName, fmOpenWrite or fmCreate);
    a_BW := TBinaryWriter.Create(a_File, TEncoding.Unicode, false);
    try
      a_BW.Write(fDiary.Version);
      a_BW.Write(fDiary.Copyright);
      a_BW.Write(fDiary.DB.Count);
      for i := 0 to fDiary.DB.Count - 1 do
      begin
        a_Day := fDiary.DB.Items[i];
        a_BW.Write(a_Day.Date);
        a_BW.Write(a_Day.WhatHappenedAdditionalyToTheTasks);
        a_BW.Write(a_Day.Breakfast);
        a_BW.Write(a_Day.Lunch);
        a_BW.Write(a_Day.Brunch);
        a_BW.Write(a_Day.TeeCoffeeTime);
        a_BW.Write(a_Day.Dinner);
        a_BW.Write(a_Day.TemperatureAtMorning);
        a_BW.Write(a_Day.PulseAtMorning);
        a_BW.Write(a_Day.HeartArrhythmiaSymbolAppearsAtMorning);
        a_BW.Write(a_Day.BloodPressureSysAtMorning);
        a_BW.Write(a_Day.BloodPressureDiaAtMorning);
        a_BW.Write(a_Day.OxygenSaturationAtMorning);
        a_BW.Write(a_Day.GlucoseLevelAtMorning);
        a_BW.Write(a_Day.WeightAtMorning);
        a_BW.Write(a_Day.TemperatureAtLunch);
        a_BW.Write(a_Day.PulseAtLunch);
        a_BW.Write(a_Day.HeartArrhythmiaSymbolAppearsAtLunch);
        a_BW.Write(a_Day.BloodPressureSysAtLunch);
        a_BW.Write(a_Day.BloodPressureDiaAtLunch);
        a_BW.Write(a_Day.OxygenSaturationAtLunch);
        a_BW.Write(a_Day.GlucoseLevelAtLunch);
        a_BW.Write(a_Day.WeightAtLunch);
        a_BW.Write(a_Day.TemperatureAtEvening);
        a_BW.Write(a_Day.PulseAtEvening);
        a_BW.Write(a_Day.HeartArrhythmiaSymbolAppearsAtEvening);
        a_BW.Write(a_Day.BloodPressureSysAtEvening);
        a_BW.Write(a_Day.BloodPressureDiaAtEvening);
        a_BW.Write(a_Day.OxygenSaturationAtEvening);
        a_BW.Write(a_Day.GlucoseLevelAtEvening);
        a_BW.Write(a_Day.WeightAtEvening);
        a_BW.Write(a_Day.HealthCondition);
        a_BW.Write(a_Day.WeatherHumidity);
        a_BW.Write(a_Day.WeatherMoonPhase);
        a_BW.Write(a_Day.WeatherPressure);
        a_BW.Write(a_Day.WeatherTemperatureAfternoon);
        a_BW.Write(a_Day.WeatherTemperatureEvening);
        a_BW.Write(a_Day.WeatherTemperatureMorning);
        a_BW.Write(a_Day.WeatherTemperatureOvernight);
        a_BW.Write(a_Day.WeatherUVIndex);
        a_BW.Write(a_Day.WeatherWindDirection);
        a_BW.Write(a_Day.WeatherWindSpeed);
        a_BW.Write(a_Day.Weather);
        a_BW.Write(a_Day.Thoughts);
        a_Length := Length(a_Day.Picture);
        a_BW.Write(a_Length);
        a_BW.Write(a_Day.Picture);
        a_BW.Write(a_Day.LastTaskID);
        a_BW.Write(a_Day.Tasks.Count);
        if (a_Day.Tasks.Count > 0) then
          for a_Task in a_Day.Tasks do
          begin
            a_BW.Write(a_Task.ID);
            a_BW.Write(a_Task.FromTime);
            a_BW.Write(a_Task.ToTime);
            a_BW.Write(a_Task.Task);
            a_BW.Write(a_Task.Notes);
          end;
        a_BW.Write(a_Day.LastConversationID);
        a_BW.Write(a_Day.Conversations.Count);
        if (a_Day.Conversations.Count > 0) then
          for a_Conversation in a_Day.Conversations do
          begin
            a_BW.Write(a_Conversation.ID);
            a_BW.Write(a_Conversation.FromTime);
            a_BW.Write(a_Conversation.ToTime);
            a_BW.Write(a_Conversation.Title);
            a_BW.Write(a_Conversation.Conversation);
          end;
        a_BW.Write(a_Day.LastShoppingID);
        a_BW.Write(a_Day.Shoppings.Count);
        if (a_Day.Shoppings.Count > 0) then
          for a_Shopping in a_Day.Shoppings do
          begin
            a_BW.Write(a_Shopping.ID);
            a_BW.Write(a_Shopping.FromTime);
            a_BW.Write(a_Shopping.ToTime);
            a_BW.Write(a_Shopping.Shop);
            a_BW.Write(a_Shopping.ShoppingList);
            a_BW.Write(a_Shopping.TotalPurchaseAmount);
          end;
      end;
      DialogUpdated := False;
      a_BW.Close;
    finally
      a_BW.Free;
      a_File.Free;
      if (a_NewFile) then
      begin
        TSDFileUtils.SaveRecentFile(fFileName);
        UpdateMenuItemsRecentFiles;
      end;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.SearchActualMonth(
  aListOfFilteredDays: TObjectList<TDay>;
  aSearchYear: Integer;
  aSearchMonth: Byte);
var
  i: Integer;
  a_Day: TDay;
begin
   for i := 0 to fDiary.DB.Count - 1 do
   begin
     a_Day := fDiary.DB.Items[i];
     if ((MonthOf(a_Day.Date) = aSearchMonth) and
         (YearOf(a_Day.Date) = aSearchYear)) then
     begin
        aListOfFilteredDays.Add(a_Day);
     end;
   end;
   aListOfFilteredDays.Sort(TComparer<TDay>.Construct(
        function (const Left, Right: TDay): Integer
        begin
          Result := CompareDate(Left.Date, Right.Date);
        end
      )
   );
end;

procedure TmainForm.SearchLast30Days(aListOfFilteredDays: TObjectList<TDay>);
var
  i: Int64;
  a_Day: TDay;
  a_FirstDay: TDateTime;
  a_LastDay: TDateTime;
begin
   a_FirstDay := fDay.Date - 30;
   a_LastDay := fDay.Date;
   for i := 0 to fDiary.DB.Count - 1 do
   begin
     a_Day := fDiary.DB.Items[i];
     if ((a_Day.Date >= a_FirstDay) and
         (a_Day.Date <= a_LastDay)) then
     begin
        aListOfFilteredDays.Add(a_Day);
     end;
   end;
   aListOfFilteredDays.Sort(TComparer<TDay>.Construct(
        function (const Left, Right: TDay): Integer
        begin
          Result := CompareDate(Left.Date, Right.Date);
        end
      )
   );
end;

procedure TmainForm.SecurePicture;
var
  a_MemoryStream: TMemoryStream;
begin
  if (Assigned(ImageOfTheDay.Picture.Graphic)) then
  begin
    a_MemoryStream := TMemoryStream.Create;
    try
      ImageOfTheDay.Picture.SaveToStream(a_MemoryStream);
      SetLength(fBytes, a_MemoryStream.Size);
      if (Length(fBytes) > 0) then
      begin
        a_MemoryStream.Position := 0;
        a_MemoryStream.ReadBuffer(fBytes[0], Length(fBytes));
      end;
    finally
      a_MemoryStream.Clear;
      FreeAndNil(a_MemoryStream);
    end;
  end;
end;

procedure TmainForm.SelectItemInListViewConversations;
var
  a_Conversation2: TConversation;
  a_ListItem: TListItem;
begin
  for a_ListItem in ListViewConversations.Items do
  begin
    a_Conversation2 := a_ListItem.Data;
    if (fConversation.ID = a_Conversation2.ID) then
    begin
      a_ListItem.Selected := True;
      Break;
    end;
  end;
end;

procedure TmainForm.SelectItemInListViewShoppings;
var
  a_Shopping2: TShopping;
  a_ListItem: TListItem;
begin
  for a_ListItem in ListViewShoppings.Items do
  begin
    a_Shopping2 := a_ListItem.Data;
    if (fShopping.ID = a_Shopping2.ID) then
    begin
      a_ListItem.Selected := True;
      Break;
    end;
  end;
end;

procedure TmainForm.SelectItemInListViewTasks;
var
  a_Task2: TTask;
  a_ListItem: TListItem;
begin
  for a_ListItem in ListViewTasks.Items do
  begin
    a_Task2 := a_ListItem.Data;
    if (fTask.ID = a_Task2.ID) then
    begin
      a_ListItem.Selected := True;
      Break;
    end;
  end;
end;

procedure TmainForm.SetData();
begin
  fDay.WhatHappenedAdditionalyToTheTasks := RichEditWhatHappenedAdditionalyToTheTasks.Text;
  fDay.Breakfast := RichEditBreakfast.Text;
  fDay.Lunch := RichEditLunch.Text;
  fDay.Brunch := RichEditBrunch.Text;
  fDay.TeeCoffeeTime := RichEditTeeCoffeeTime.Text;
  fDay.Dinner := RichEditDinner.Text;
  fDay.TemperatureAtMorning := StrToFloat(EditTemperature1.Text);
  fDay.PulseAtMorning := StrToFloat(EditPuls1.Text);
  fDay.HeartArrhythmiaSymbolAppearsAtMorning := CheckBoxHeartArrhythmiaSymbolAppears1.Checked;
  fDay.BloodPressureSysAtMorning := StrToFloat(EditBloodPressureSys1.Text);
  fDay.BloodPressureDiaAtMorning := StrToFloat(EditBloodPressureDia1.Text);
  fDay.OxygenSaturationAtMorning := StrToFloat(EditOxygenSaturation1.Text);
  fDay.GlucoseLevelAtMorning := StrToFloat(EditGlucoseLevel1.Text);
  fDay.WeightAtMorning := StrToFloat(EditWeight1.Text);
  fDay.TemperatureAtLunch := StrToFloat(EditTemperature2.Text);
  fDay.PulseAtLunch := StrToFloat(EditPuls2.Text);
  fDay.HeartArrhythmiaSymbolAppearsAtLunch := CheckBoxHeartArrhythmiaSymbolAppears2.Checked;
  fDay.BloodPressureSysAtLunch := StrToFloat(EditBloodPressureSys2.Text);
  fDay.BloodPressureDiaAtLunch := StrToFloat(EditBloodPressureDia2.Text);
  fDay.OxygenSaturationAtLunch := StrToFloat(EditOxygenSaturation2.Text);
  fDay.GlucoseLevelAtLunch := StrToFloat(EditGlucoseLevel2.Text);
  fDay.WeightAtLunch := StrToFloat(EditWeight2.Text);
  fDay.TemperatureAtEvening := StrToFloat(EditTemperature3.Text);
  fDay.PulseAtEvening := StrToFloat(EditPuls3.Text);
  fDay.HeartArrhythmiaSymbolAppearsAtEvening := CheckBoxHeartArrhythmiaSymbolAppears3.Checked;
  fDay.BloodPressureSysAtEvening := StrToFloat(EditBloodPressureSys3.Text);
  fDay.BloodPressureDiaAtEvening := StrToFloat(EditBloodPressureDia3.Text);
  fDay.OxygenSaturationAtEvening := StrToFloat(EditOxygenSaturation3.Text);
  fDay.GlucoseLevelAtEvening := StrToFloat(EditGlucoseLevel3.Text);
  fDay.WeightAtEvening := StrToFloat(EditWeight3.Text);
  fDay.HealthCondition := RichEditlHealthCondition.Text;
  fDay.WeatherHumidity := StrToInt(EditWeatherHumidity.Text);
  fDay.WeatherMoonPhase := ComboBoxWeatherMoonPhase.Text;
  fDay.WeatherPressure := StrToFloat(EditWeatherPressure.Text);
  fDay.WeatherTemperatureAfternoon := StrToInt(EditWeatherTemperatureAfternoon.Text);
  fDay.WeatherTemperatureEvening := StrToInt(EditWeatherTemperatureEvening.Text);
  fDay.WeatherTemperatureMorning := StrToInt(EditWeatherTemperatureMorning.Text);
  fDay.WeatherTemperatureOvernight := StrToInt(EditWeatherTemperatureOvernight.Text);
  fDay.WeatherUVIndex := StrToInt(EditWeatherUVIndex.Text);
  fDay.WeatherWindDirection := ComboBoxWeatherWindDirection.Text;
  fDay.WeatherWindSpeed := StrToInt(EditWeatherWindSpeed.Text);
  fDay.Weather := RichEditWeatherToday.Text;
  fDay.Thoughts := RichEditThoughts.Text;
  if (Length(fBytes) > 0) then
    fDay.Picture := Copy(fBytes)
  else
    fDay.SetEmptyPicture;
  SetLength(fBytes, 0);
  SetDataTask;
  SetDataConversation;
  SetDataShopping;
end;

procedure TmainForm.SetDataConversation;
begin
  if (Assigned(fConversation)) then
  begin
    fConversation.FromTime := DateTimePickerFrom.Time;
    fConversation.ToTime := DateTimePickerTo.Time;
    fConversation.Title := EditConversationTitle.Text;
    fConversation.Conversation := RichEditConversation.Text;
  end;
end;

procedure TmainForm.SetDataShopping;
begin
  if (Assigned(fShopping)) then
  begin
    fShopping.FromTime := DateTimePickerShoppingFrom.Time;
    fShopping.ToTime := DateTimePickerShoppingTo.Time;
    fShopping.Shop := EditShop.Text;
    fShopping.ShoppingList := RichEditShoppingList.Text;
    if (EditTotalPurchaseAmount.Text <> '') then
      fShopping.TotalPurchaseAmount := StrToFloat(EditTotalPurchaseAmount.Text)
    else
      fShopping.TotalPurchaseAmount := 0;
  end;
end;

procedure TmainForm.SetDataTask;
begin
  if (Assigned(fTask)) then
  begin
    fTask.FromTime := DateTimePickerTaskFrom.Time;
    fTask.ToTime := DateTimePickerTaskTo.Time;
    fTask.Task := EditTask.Text;
    fTask.Notes := RichEditNotes.Text;
  end;
end;

procedure TmainForm.SetDialogUpdated(const aValue: Boolean);
begin
  fDialogUpdated := aValue;
  ToolButtonSaveFile.Enabled := aValue;
  MenuItemSave.Enabled := aValue;
end;

procedure TmainForm.TestData;
var
  a_Result: Boolean;
  a_Amount: Double;
begin
  SecurePicture;
  a_Result :=
     ((CompareStr(fDay.WhatHappenedAdditionalyToTheTasks, RichEditWhatHappenedAdditionalyToTheTasks.Text) <> 0) or
      (CompareStr(fDay.Breakfast, RichEditBreakfast.Text) <> 0) or
      (CompareStr(fDay.Lunch, RichEditLunch.Text) <> 0) or
      (CompareStr(fDay.Brunch, RichEditBrunch.Text) <> 0) or
      (CompareStr(fDay.TeeCoffeeTime, RichEditTeeCoffeeTime.Text) <> 0) or
      (CompareStr(fDay.Dinner, RichEditDinner.Text) <> 0) or
      (fDay.TemperatureAtMorning <> StrToFloat(EditTemperature1.Text)) or
      (fDay.PulseAtMorning <> StrToFloat(EditPuls1.Text)) or
      (fDay.HeartArrhythmiaSymbolAppearsAtMorning <> CheckBoxHeartArrhythmiaSymbolAppears1.Checked) or
      (fDay.BloodPressureSysAtMorning <> StrToFloat(EditBloodPressureSys1.Text)) or
      (fDay.BloodPressureDiaAtMorning <> StrToFloat(EditBloodPressureDia1.Text)) or
      (fDay.OxygenSaturationAtMorning <> StrToFloat(EditOxygenSaturation1.Text)) or
      (fDay.GlucoseLevelAtMorning <> StrToFloat(EditGlucoseLevel1.Text)) or
      (fDay.WeightAtMorning <> StrToFloat(EditWeight1.Text)) or
      (fDay.TemperatureAtLunch <> StrToFloat(EditTemperature2.Text)) or
      (fDay.PulseAtLunch <> StrToFloat(EditPuls2.Text)) or
      (fDay.HeartArrhythmiaSymbolAppearsAtLunch <> CheckBoxHeartArrhythmiaSymbolAppears2.Checked) or
      (fDay.BloodPressureSysAtLunch <> StrToFloat(EditBloodPressureSys2.Text)) or
      (fDay.BloodPressureDiaAtLunch <> StrToFloat(EditBloodPressureDia2.Text)) or
      (fDay.OxygenSaturationAtLunch <> StrToFloat(EditOxygenSaturation2.Text)) or
      (fDay.GlucoseLevelAtLunch <> StrToFloat(EditGlucoseLevel2.Text)) or
      (fDay.WeightAtLunch <> StrToFloat(EditWeight2.Text)) or
      (fDay.TemperatureAtEvening <> StrToFloat(EditTemperature3.Text)) or
      (fDay.PulseAtEvening <> StrToFloat(EditPuls3.Text)) or
      (fDay.HeartArrhythmiaSymbolAppearsAtEvening <> CheckBoxHeartArrhythmiaSymbolAppears3.Checked) or
      (fDay.BloodPressureSysAtEvening <> StrToFloat(EditBloodPressureSys3.Text)) or
      (fDay.BloodPressureDiaAtEvening <> StrToFloat(EditBloodPressureDia3.Text)) or
      (fDay.OxygenSaturationAtEvening <> StrToFloat(EditOxygenSaturation3.Text)) or
      (fDay.GlucoseLevelAtEvening <> StrToFloat(EditGlucoseLevel3.Text)) or
      (fDay.WeightAtEvening <> StrToFloat(EditWeight3.Text)) or
      (CompareStr(fDay.HealthCondition, RichEditlHealthCondition.Text) <> 0) or
      (fDay.WeatherHumidity <> StrToInt(EditWeatherHumidity.Text)) or
      (CompareStr(fDay.WeatherMoonPhase, ComboBoxWeatherMoonPhase.Text) <> 0) or
      (fDay.WeatherPressure <> StrToFloat(EditWeatherPressure.Text)) or
      (fDay.WeatherTemperatureAfternoon <> StrToInt(EditWeatherTemperatureAfternoon.Text)) or
      (fDay.WeatherTemperatureEvening <> StrToInt(EditWeatherTemperatureEvening.Text)) or
      (fDay.WeatherTemperatureMorning <> StrToInt(EditWeatherTemperatureMorning.Text)) or
      (fDay.WeatherTemperatureOvernight <> StrToInt(EditWeatherTemperatureOvernight.Text)) or
      (fDay.WeatherUVIndex <> StrToInt(EditWeatherUVIndex.Text)) or
      (CompareStr(fDay.WeatherWindDirection, ComboBoxWeatherWindDirection.Text) <> 0) or
      (fDay.WeatherWindSpeed <> StrToInt(EditWeatherWindSpeed.Text)) or
      (CompareStr(fDay.Weather, RichEditWeatherToday.Text) <> 0) or
      (CompareStr(fDay.Thoughts, RichEditThoughts.Text) <> 0)) or
      (not TSDByteUtils.SameByteArray(fDay.Picture, fBytes));
  if (not a_Result) and (Assigned(fTask)) then
     a_Result :=
       (fTask.FromTime <> DateTimePickerTaskFrom.Time) or
       (fTask.ToTime <> DateTimePickerTaskTo.Time) or
       (CompareStr(fTask.Task, EditTask.Text) <> 0) or
       (CompareStr(fTask.Notes, RichEditNotes.Text) <> 0);
  if (not a_Result) and (Assigned(fConversation)) then
     a_Result :=
       (fConversation.FromTime <> DateTimePickerFrom.Time) or
       (fConversation.ToTime <> DateTimePickerTo.Time) or
       (CompareStr(fConversation.Title, EditConversationTitle.Text) <> 0) or
       (CompareStr(fConversation.Conversation, RichEditConversation.Text) <> 0);
  if (not a_Result) and (Assigned(fShopping)) then
  begin
    if (EditTotalPurchaseAmount.Text = '') then
      a_Amount := 0
    else
      a_Amount := StrToFloat(EditTotalPurchaseAmount.Text);
     a_Result :=
       (fShopping.FromTime <> DateTimePickerShoppingFrom.Time) or
       (fShopping.ToTime <> DateTimePickerShoppingTo.Time) or
       (CompareStr(fShopping.Shop, EditShop.Text) <> 0) or
       (CompareStr(fShopping.ShoppingList, RichEditShoppingList.Text) <> 0) or
       (fShopping.TotalPurchaseAmount <> a_Amount);
  end;
  if (a_Result) then
    DialogUpdated := True;
end;

procedure TmainForm.ToolButtonExitClick(Sender: TObject);
begin
  Close;
end;

procedure TmainForm.ToolButtonSaveFileClick(Sender: TObject);
begin
  MenuItemSaveClick(Sender);
end;

procedure TmainForm.ToolButtonSaveFileAsClick(Sender: TObject);
begin
  MenuItemSaveAsClick(Sender);
end;

procedure TmainForm.ToolButtonOpenFileClick(Sender: TObject);
begin
  MenuItemOpenFileClick(Sender);
end;

procedure TmainForm.ToolButtonOpenNewFileClick(Sender: TObject);
begin
  MenuItemNewClick(Sender);
end;

procedure TmainForm.UpdateListViewConversations;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    TestData;
    SetDataConversation;
    FillListViewConversations;
    SelectItemInListViewConversations;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.UpdateListViewShoppings;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    TestData;
    SetDataShopping;
    FillListViewShoppings;
    SelectItemInListViewShoppings;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.UpdateListViewTasks;
begin
  if (fBusy) then
    Exit;
  Screen.Cursor := crHourGlass;
  fBusy := True;
  try
    TestData;
    SetDataTask;
    FillListViewTasks;
    SelectItemInListViewTasks;
  finally
    fBusy := False;
    Screen.Cursor := crDefault;
  end;
end;

procedure TmainForm.UpdateHealthChart;
var
  i: Int64;
  a_Day: TDay;
  a_ListOfFilteredDays: TObjectList<TDay>;
begin
  a_ListOfFilteredDays := TObjectList<TDay>.Create;
  a_ListOfFilteredDays.OwnsObjects := False;
  try
    SearchLast30Days(a_ListOfFilteredDays);
    with ChartHealthValue do
    begin
      Legend.Visible := False;
      Title.Text.Clear;
      Series[0].Clear;
      Series[1].Clear;
      Series[2].Clear;
      Series[1].Visible := False;
      Series[2].Visible := False;
      Series[0].Title := 'Morning';
      Series[1].Title := 'Afternoon';
      Series[2].Title := 'Evening';
    end;
    case RadioGroupChartType.ItemIndex of
      HEALTH_VALUE_CHART_TYPE_MORNING:
      begin
        ChartHealthValue.Series[0].Title := 'Morning';
        case ComboBoxHealthValue.ItemIndex of
          HEALTH_VALUE_TEMPERATURE:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Temperature');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.TemperatureAtMorning);
              end;
            end;
          end;
          HEALTH_VALUE_PULSE:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Pulse');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.PulseAtMorning);
              end;
            end;
          end;
          HEALTH_VALUE_BLOOD_PRESSURE_SYS:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Blood pressure Sys');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.BloodPressureSysAtMorning);
              end;
            end;
          end;
          HEALTH_VALUE_BLOOD_PRESSURE_DIA:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Blood pressure Dia');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.BloodPressureDiaAtMorning);
              end;
            end;
          end;
          HEALTH_VALUE_OXYGEN_SATURATION:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Oxygen saturation in %');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.OxygenSaturationAtMorning);
              end;
            end;
          end;
          HEALTH_VALUE_GLUCOSE_LEVEL:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Glucose level');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.GlucoseLevelAtMorning);
              end;
            end;
          end;
          HEALTH_VALUE_WEIGHT:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Weight');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.WeightAtMorning);
              end;
            end;
          end;
        end;
      end;
      HEALTH_VALUE_CHART_TYPE_AFTERNOON:
      begin
        ChartHealthValue.Series[0].Title := 'Afternoon';
        case ComboBoxHealthValue.ItemIndex of
          HEALTH_VALUE_TEMPERATURE:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Temperature');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.TemperatureAtLunch);
              end;
            end;
          end;
          HEALTH_VALUE_PULSE:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Pulse');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.PulseAtLunch);
              end;
            end;
          end;
          HEALTH_VALUE_BLOOD_PRESSURE_SYS:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Blood pressure Sys');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.BloodPressureSysAtLunch);
              end;
            end;
          end;
          HEALTH_VALUE_BLOOD_PRESSURE_DIA:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Blood pressure Dia');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.BloodPressureDiaAtLunch);
              end;
            end;
          end;
          HEALTH_VALUE_OXYGEN_SATURATION:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Oxygen saturation in %');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.OxygenSaturationAtLunch);
              end;
            end;
          end;
          HEALTH_VALUE_GLUCOSE_LEVEL:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Glucose level');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.GlucoseLevelAtLunch);
              end;
            end;
          end;
          HEALTH_VALUE_WEIGHT:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Weight');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.WeightAtLunch);
              end;
            end;
          end;
        end;
      end;
      HEALTH_VALUE_CHART_TYPE_EVENING:
      begin
        ChartHealthValue.Series[0].Title := 'Evening';
        case ComboBoxHealthValue.ItemIndex of
          HEALTH_VALUE_TEMPERATURE:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Temperature');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.TemperatureAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_PULSE:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Pulse');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.PulseAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_BLOOD_PRESSURE_SYS:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Blood pressure Sys');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.BloodPressureSysAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_BLOOD_PRESSURE_DIA:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Blood pressure Dia');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.BloodPressureDiaAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_OXYGEN_SATURATION:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Oxygen saturation in %');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.OxygenSaturationAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_GLUCOSE_LEVEL:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Glucose level');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.GlucoseLevelAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_WEIGHT:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Weight');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.WeightAtEvening);
              end;
            end;
          end;
        end;
      end;
      HEALTH_VALUE_CHART_TYPE_ALL:
      begin
        ChartHealthValue.Legend.Visible := True;
        ChartHealthValue.Series[1].Visible := True;
        ChartHealthValue.Series[2].Visible := True;
        case ComboBoxHealthValue.ItemIndex of
          HEALTH_VALUE_TEMPERATURE:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Temperature');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.TemperatureAtMorning);
                Series[1].AddXY(a_Day.Date, a_Day.TemperatureAtLunch);
                Series[2].AddXY(a_Day.Date, a_Day.TemperatureAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_PULSE:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Pulse');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.PulseAtMorning);
                Series[1].AddXY(a_Day.Date, a_Day.PulseAtLunch);
                Series[2].AddXY(a_Day.Date, a_Day.PulseAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_BLOOD_PRESSURE_SYS:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Blood pressure Sys');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.BloodPressureSysAtMorning);
                Series[1].AddXY(a_Day.Date, a_Day.BloodPressureSysAtLunch);
                Series[2].AddXY(a_Day.Date, a_Day.BloodPressureSysAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_BLOOD_PRESSURE_DIA:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Blood pressure Dia');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.BloodPressureDiaAtMorning);
                Series[1].AddXY(a_Day.Date, a_Day.BloodPressureDiaAtLunch);
                Series[2].AddXY(a_Day.Date, a_Day.BloodPressureDiaAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_OXYGEN_SATURATION:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Oxygen saturation in %');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.OxygenSaturationAtMorning);
                Series[1].AddXY(a_Day.Date, a_Day.OxygenSaturationAtLunch);
                Series[2].AddXY(a_Day.Date, a_Day.OxygenSaturationAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_GLUCOSE_LEVEL:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Glucose level');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.GlucoseLevelAtMorning);
                Series[1].AddXY(a_Day.Date, a_Day.GlucoseLevelAtLunch);
                Series[2].AddXY(a_Day.Date, a_Day.GlucoseLevelAtEvening);
              end;
            end;
          end;
          HEALTH_VALUE_WEIGHT:
          begin
            with ChartHealthValue do
            begin
              Title.Text.Add('Health value: Weight');
              for i := 0 to a_ListOfFilteredDays.Count - 1 do
              begin
                a_Day := a_ListOfFilteredDays.Items[i];
                Series[0].AddXY(a_Day.Date, a_Day.WeightAtMorning);
                Series[1].AddXY(a_Day.Date, a_Day.WeightAtLunch);
                Series[2].AddXY(a_Day.Date, a_Day.WeightAtEvening);
              end;
            end;
          end;
        end;
      end;
    end;
  finally
    a_ListOfFilteredDays.Free;
  end;
end;

procedure TmainForm.UpdateMenuItemsRecentFiles;
begin
  if (TSDFileUtils.RecentFiles[1] <> '') then
  begin
    MenuItemRecentFile1.Caption := '&A ' + ExtractFileName(TSDFileUtils.RecentFiles[1]);
    MenuItemRecentFile1.Visible := true;
  end
  else
  begin
    MenuItemRecentFile1.Caption := '';
    MenuItemRecentFile1.Visible := False;
  end;
  if (TSDFileUtils.RecentFiles[2] <> '') then
  begin
    MenuItemRecentFile2.Caption := '&B ' + ExtractFileName(TSDFileUtils.RecentFiles[2]);
    MenuItemRecentFile2.Visible := true;
  end
  else
  begin
    MenuItemRecentFile2.Caption := '';
    MenuItemRecentFile2.Visible := False;
  end;
  if (TSDFileUtils.RecentFiles[3] <> '') then
  begin
    MenuItemRecentFile3.Caption := '&C ' + ExtractFileName(TSDFileUtils.RecentFiles[3]);
    MenuItemRecentFile3.Visible := true;
  end
  else
  begin
    MenuItemRecentFile3.Caption := '';
    MenuItemRecentFile3.Visible := False;
  end;
  if (TSDFileUtils.RecentFiles[4] <> '') then
  begin
    MenuItemRecentFile4.Caption := '&D ' + ExtractFileName(TSDFileUtils.RecentFiles[4]);
    MenuItemRecentFile4.Visible := true;
  end
  else
  begin
    MenuItemRecentFile4.Caption := '';
    MenuItemRecentFile4.Visible := False;
  end;
  if (TSDFileUtils.RecentFiles[5] <> '') then
  begin
    MenuItemRecentFile5.Caption := '&E ' + ExtractFileName(TSDFileUtils.RecentFiles[5]);
    MenuItemRecentFile5.Visible := true;
  end
  else
  begin
    MenuItemRecentFile5.Caption := '';
    MenuItemRecentFile5.Visible := False;
  end;
  if (TSDFileUtils.RecentFiles[6] <> '') then
  begin
    MenuItemRecentFile6.Caption := '&F ' + ExtractFileName(TSDFileUtils.RecentFiles[6]);
    MenuItemRecentFile6.Visible := true;
  end
  else
  begin
    MenuItemRecentFile6.Caption := '';
    MenuItemRecentFile6.Visible := False;
  end;
end;

procedure TmainForm.UpdateWeatherChart;
var
  i: Int64;
  a_Day: TDay;
  a_ListOfFilteredDays: TObjectList<TDay>;
begin
  a_ListOfFilteredDays := TObjectList<TDay>.Create;
  a_ListOfFilteredDays.OwnsObjects := False;
  try
    SearchLast30Days(a_ListOfFilteredDays);
    with ChartWeatherValue do
    begin
      Title.Text.Clear;
      Series[0].Clear;
      Series[0].Title := 'Value';
    end;
    case ComboBoxWeatherValue.ItemIndex of
      WEATHER_TEMPERATURE_MORNING:
      begin
        with ChartWeatherValue do
        begin
          Title.Text.Add('Weather value: Temperature morning');
          for i := 0 to a_ListOfFilteredDays.Count - 1 do
          begin
            a_Day := a_ListOfFilteredDays.Items[i];
            Series[0].AddXY(a_Day.Date, a_Day.WeatherTemperatureMorning);
          end;
        end;
      end;
      WEATHER_TEMPERATURE_AFTERNOON:
      begin
        with ChartWeatherValue do
        begin
          Title.Text.Add('Weather value: Temperature afternoon');
          for i := 0 to a_ListOfFilteredDays.Count - 1 do
          begin
            a_Day := a_ListOfFilteredDays.Items[i];
            Series[0].AddXY(a_Day.Date, a_Day.WeatherTemperatureAfternoon);
          end;
        end;
      end;
      WEATHER_TEMPERATURE_EVENING:
      begin
        with ChartWeatherValue do
        begin
          Title.Text.Add('Weather value: Temperature evening');
          for i := 0 to a_ListOfFilteredDays.Count - 1 do
          begin
            a_Day := a_ListOfFilteredDays.Items[i];
            Series[0].AddXY(a_Day.Date, a_Day.WeatherTemperatureEvening);
          end;
        end;
      end;
      WEATHER_TEMPERATURE_OVERNIGHT:
      begin
        with ChartWeatherValue do
        begin
          Title.Text.Add('Weather value: Temperature overnight');
          for i := 0 to a_ListOfFilteredDays.Count - 1 do
          begin
            a_Day := a_ListOfFilteredDays.Items[i];
            Series[0].AddXY(a_Day.Date, a_Day.WeatherTemperatureOvernight);
          end;
        end;
      end;
      WEATHER_HUMIDITY:
      begin
        with ChartWeatherValue do
        begin
          Title.Text.Add('Weather value: Humidity %');
          for i := 0 to a_ListOfFilteredDays.Count - 1 do
          begin
            a_Day := a_ListOfFilteredDays.Items[i];
            Series[0].AddXY(a_Day.Date, a_Day.WeatherHumidity);
          end;
        end;
      end;
      WEATHER_PRESSURE:
      begin
        with ChartWeatherValue do
        begin
          Title.Text.Add('Weather value: Pressure hPa');
          for i := 0 to a_ListOfFilteredDays.Count - 1 do
          begin
            a_Day := a_ListOfFilteredDays.Items[i];
            Series[0].AddXY(a_Day.Date, a_Day.WeatherPressure);
           end;
        end;
      end;
      WEATHER_WIND_SPEED:
      begin
        with ChartWeatherValue do
        begin
          Title.Text.Add('Weather value: Wind speed km/h');
          for i := 0 to a_ListOfFilteredDays.Count - 1 do
          begin
            a_Day := a_ListOfFilteredDays.Items[i];
            Series[0].AddXY(a_Day.Date, a_Day.WeatherWindSpeed);
          end;
        end;
      end;
      WEATHER_UV_INDEX:
      begin
        with ChartWeatherValue do
        begin
          Title.Text.Add('Weather value: UV Index');
          for i := 0 to a_ListOfFilteredDays.Count - 1 do
          begin
            a_Day := a_ListOfFilteredDays.Items[i];
            Series[0].AddXY(a_Day.Date, a_Day.WeatherUVIndex);
          end;
        end;
      end;
    end;
  finally
    a_ListOfFilteredDays.Free;
  end;
end;

end.
