//
// 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 UnitDiary;

interface
uses
  SysUtils, System.Generics.Collections;

type
  TTask = class(TObject)
  private
    fID: Int64;
    fFromTime: TTime;
    fToTime: TTime;
    fTask: String;
    fNotes: String;
  public
    constructor Create;
    property ID: Int64
      read fID
      write fID;
    property FromTime: TTime
      read fFromTime
      write fFromTime;
    property ToTime: TTime
      read fToTime
      write fToTime;
    property Task: String
      read fTask
      write fTask;
    property Notes: String
      read fNotes
      write fNotes;
  end;

  TConversation = class(TObject)
  private
    fID: Int64;
    fFromTime: TTime;
    fToTime: TTime;
    fTitle: String;
    fConversation: String;
  public
    constructor Create;
    property ID: Int64
      read fID
      write fID;
    property FromTime: TTime
      read fFromTime
      write fFromTime;
    property ToTime: TTime
      read fToTime
      write fToTime;
    property Title: String
      read fTitle
      write fTitle;
    property Conversation: String
      read fConversation
      write fConversation;
  end;

  TShopping = class(TObject)
  private
    fID: Int64;
    fFromTime: TTime;
    fToTime: TTime;
    fShop: String;
    fShoppingList: String;
    fTotalPurchaseAmount: Double;
  public
    constructor Create;
    property ID: Int64
      read fID
      write fID;
    property FromTime: TTime
      read fFromTime
      write fFromTime;
    property ToTime: TTime
      read fToTime
      write fToTime;
    property Shop: String
      read fShop
      write fShop;
    property ShoppingList: String
      read fShoppingList
      write fShoppingList;
    property TotalPurchaseAmount: Double
      read fTotalPurchaseAmount
      write fTotalPurchaseAmount;
  end;

  TDay = class(TObject)
  private
    var
      fDate: TDateTime;
      fWhatHappenedAdditionalyToTheTasks: String;
      fBreakfast: String;
      fLunch: String;
      fBrunch: String;
      fTeeCoffeeTime: String;
      fDinner: String;
      fTemperatureAtMorning: Double;
      fPulseAtMorning: Double;
      fHeartArrhythmiaSymbolAppearsAtMorning: Boolean;
      fBloodPressureSysAtMorning: Double;
      fBloodPressureDiaAtMorning: Double;
      fOxygenSaturationAtMorning: Double;
      fGlucoseLevelAtMorning: Double;
      fWeightAtMorning: Double;
      fTemperatureAtLunch: Double;
      fPulseAtLunch: Double;
      fHeartArrhythmiaSymbolAppearsAtLunch: Boolean;
      fBloodPressureSysAtLunch: Double;
      fBloodPressureDiaAtLunch: Double;
      fOxygenSaturationAtLunch: Double;
      fGlucoseLevelAtLunch: Double;
      fWeightAtLunch: Double;
      fTemperatureAtEvening: Double;
      fPulseAtEvening: Double;
      fHeartArrhythmiaSymbolAppearsAtEvening: Boolean;
      fBloodPressureSysAtEvening: Double;
      fBloodPressureDiaAtEvening: Double;
      fOxygenSaturationAtEvening: Double;
      fGlucoseLevelAtEvening: Double;
      fWeightAtEvening: Double;
      fHealthCondition: String;
      fWeatherHumidity: Integer;
      fWeatherMoonPhase: String;
      fWeatherPressure: Double;
      fWeatherTemperatureAfternoon: Integer;
      fWeatherTemperatureEvening: Integer;
      fWeatherTemperatureMorning: Integer;
      fWeatherTemperatureOvernight: Integer;
      fWeatherUVIndex: Integer;
      fWeatherWindDirection: String;
      fWeatherWindSpeed: Integer;
      fWeather: String;
      fThoughts: String;
      fPicture: TBytes;
      fLastTaskID: Int64;
      fTasks: TObjectList<TTask>;
      fLastConversationID: Int64;
      fConversations: TObjectList<TConversation>;
      fLastShoppingID: Int64;
      fShoppings: TObjectList<TShopping>;
  public
    constructor Create(aDate: TDateTime);
    destructor Destroy; override;
    procedure SetEmptyPicture;
    property Date: TDateTime
      read fDate
      write fDate;
    property WhatHappenedAdditionalyToTheTasks: String
      read fWhatHappenedAdditionalyToTheTasks
      write fWhatHappenedAdditionalyToTheTasks;
    property Breakfast: String
      read fBreakfast
      write fBreakfast;
    property Lunch: String
      read fLunch
      write fLunch;
    property Brunch: String
      read fBrunch
      write fBrunch;
    property TeeCoffeeTime: String
      read fTeeCoffeeTime
      write fTeeCoffeeTime;
    property Dinner: String
      read fDinner
      write fDinner;
    property TemperatureAtMorning: Double
      read fTemperatureAtMorning
      write fTemperatureAtMorning;
    property PulseAtMorning: Double
      read fPulseAtMorning
      write fPulseAtMorning;
    property HeartArrhythmiaSymbolAppearsAtMorning: Boolean
      read fHeartArrhythmiaSymbolAppearsAtMorning
      write fHeartArrhythmiaSymbolAppearsAtMorning;
    property BloodPressureSysAtMorning: Double
      read fBloodPressureSysAtMorning
      write fBloodPressureSysAtMorning;
    property BloodPressureDiaAtMorning: Double
      read fBloodPressureDiaAtMorning
      write fBloodPressureDiaAtMorning;
    property OxygenSaturationAtMorning: Double
      read fOxygenSaturationAtMorning
      write fOxygenSaturationAtMorning;
    property GlucoseLevelAtMorning: Double
      read fGlucoseLevelAtMorning
      write fGlucoseLevelAtMorning;
    property WeightAtMorning: Double
      read fWeightAtMorning
      write fWeightAtMorning;
    property TemperatureAtLunch: Double
      read fTemperatureAtLunch
      write fTemperatureAtLunch;
    property PulseAtLunch: Double
      read fPulseAtLunch
      write fPulseAtLunch;
    property HeartArrhythmiaSymbolAppearsAtLunch: Boolean
      read fHeartArrhythmiaSymbolAppearsAtLunch
      write fHeartArrhythmiaSymbolAppearsAtLunch;
    property BloodPressureSysAtLunch: Double
      read fBloodPressureSysAtLunch
      write fBloodPressureSysAtLunch;
    property BloodPressureDiaAtLunch: Double
      read fBloodPressureDiaAtLunch
      write fBloodPressureDiaAtLunch;
    property OxygenSaturationAtLunch: Double
      read fOxygenSaturationAtLunch
      write fOxygenSaturationAtLunch;
    property GlucoseLevelAtLunch: Double
      read fGlucoseLevelAtLunch
      write fGlucoseLevelAtLunch;
    property WeightAtLunch: Double
      read fWeightAtLunch
      write fWeightAtLunch;
    property TemperatureAtEvening: Double
      read fTemperatureAtEvening
      write fTemperatureAtEvening;
    property PulseAtEvening: Double
      read fPulseAtEvening
      write fPulseAtEvening;
    property HeartArrhythmiaSymbolAppearsAtEvening: Boolean
      read fHeartArrhythmiaSymbolAppearsAtEvening
      write fHeartArrhythmiaSymbolAppearsAtEvening;
    property BloodPressureSysAtEvening: Double
      read fBloodPressureSysAtEvening
      write fBloodPressureSysAtEvening;
    property BloodPressureDiaAtEvening: Double
      read fBloodPressureDiaAtEvening
      write fBloodPressureDiaAtEvening;
    property OxygenSaturationAtEvening: Double
      read fOxygenSaturationAtEvening
      write fOxygenSaturationAtEvening;
    property GlucoseLevelAtEvening: Double
      read fGlucoseLevelAtEvening
      write fGlucoseLevelAtEvening;
    property WeightAtEvening: Double
      read fWeightAtEvening
      write fWeightAtEvening;
    property HealthCondition: String
      read fHealthCondition
      write fHealthCondition;
    property WeatherHumidity: Integer
      read fWeatherHumidity
      write fWeatherHumidity;
    property WeatherMoonPhase: String
      read fWeatherMoonPhase
      write fWeatherMoonPhase;
    property WeatherPressure: Double
      read fWeatherPressure
      write fWeatherPressure;
    property WeatherTemperatureAfternoon: Integer
      read fWeatherTemperatureAfternoon
      write fWeatherTemperatureAfternoon;
    property WeatherTemperatureEvening: Integer
      read fWeatherTemperatureEvening
      write fWeatherTemperatureEvening;
    property WeatherTemperatureMorning: Integer
      read fWeatherTemperatureMorning
      write fWeatherTemperatureMorning;
    property WeatherTemperatureOvernight: Integer
      read fWeatherTemperatureOvernight
      write fWeatherTemperatureOvernight;
    property WeatherUVIndex: Integer
      read fWeatherUVIndex
      write fWeatherUVIndex;
    property WeatherWindDirection: String
      read fWeatherWindDirection
      write fWeatherWindDirection;
    property WeatherWindSpeed: Integer
      read fWeatherWindSpeed
      write fWeatherWindSpeed;
    property Weather: String
      read fWeather
      write fWeather;
    property Thoughts: String
      read fThoughts
      write fThoughts;
    property Picture: TBytes
      read fPicture
      write fPicture;
    property LastTaskID: Int64
      read fLastTaskID
      write fLastTaskID;
    property Tasks: TObjectList<TTask>
      read fTasks
      write fTasks;
    property LastConversationID: Int64
      read fLastConversationID
      write fLastConversationID;
    property Conversations: TObjectList<TConversation>
      read fConversations
      write fConversations;
    property LastShoppingID: Int64
      read fLastShoppingID
      write fLastShoppingID;
    property Shoppings: TObjectList<TShopping>
      read fShoppings
      write fShoppings;
  end;

  TDiary = class(TObject)
  private
    var
      fCopyright: String;
      fDB: TObjectList<TDay>;
      fVersion: Integer;
  public
    constructor Create;
    destructor Destroy; override;
    function GetDay(aDate: TDateTime): TDay;
    property Copyright: String read fCopyright write fCopyright;
    property DB: TObjectList<TDay> read fDB write fDB;
    property Version: Integer read fVersion write fVersion;
  end;

  TTaskOfTheDay = class(TObject)
  private
    var
      fStartDateTime: TDateTime;
      fEndDateTime: TDateTime;
      fTask: String;
      fNotice: String;
  public
    constructor Create;
    property StartDateTime: TDateTime
      read fStartDateTime
      write fStartDateTime;
    property EndDateTime: TDateTime
      read fEndDateTime
      write fEndDateTime;
    property Task: String
      read fTask
      write fTask;
    property Notice: String
      read fNotice
      write fNotice;
  end;


const
  FILE_VERSION = 10;
  MAX_BACKUP = 5;

  HEALTH_VALUE_TEMPERATURE        = 0;
  HEALTH_VALUE_PULSE              = 1;
  HEALTH_VALUE_BLOOD_PRESSURE_SYS = 2;
  HEALTH_VALUE_BLOOD_PRESSURE_DIA = 3;
  HEALTH_VALUE_OXYGEN_SATURATION  = 4;
  HEALTH_VALUE_GLUCOSE_LEVEL      = 5;
  HEALTH_VALUE_WEIGHT             = 6;

  HEALTH_VALUE_CHART_TYPE_MORNING   = 0;
  HEALTH_VALUE_CHART_TYPE_AFTERNOON = 1;
  HEALTH_VALUE_CHART_TYPE_EVENING   = 2;
  HEALTH_VALUE_CHART_TYPE_ALL       = 3;

  WEATHER_TEMPERATURE_MORNING   = 0;
  WEATHER_TEMPERATURE_AFTERNOON = 1;
  WEATHER_TEMPERATURE_EVENING   = 2;
  WEATHER_TEMPERATURE_OVERNIGHT = 3;
  WEATHER_HUMIDITY              = 4;
  WEATHER_PRESSURE              = 5;
  WEATHER_WIND_SPEED            = 6;
  WEATHER_UV_INDEX              = 7;

implementation

uses
  DateUtils, System.Generics.Defaults;

constructor TTask.Create;
begin
  fID := 0;
  fFromTime := EncodeTime(0, 0, 0, 0);
  fToTime := EncodeTime(0, 1, 0, 0);
  fTask := 'New Task';
  fNotes := '';
end;

constructor TConversation.Create;
begin
  fID := 0;
  fFromTime := EncodeTime(0, 0, 0, 0);
  fToTime := EncodeTime(0, 1, 0, 0);
  fTitle := 'New Conversation';
  fConversation := '';
end;

constructor TShopping.Create;
begin
  fID := 0;
  fFromTime := EncodeTime(0, 0, 0, 0);
  fToTime := EncodeTime(0, 1, 0, 0);
  fShop := 'New Shop';
  fShoppingList := '';
  fTotalPurchaseAmount := 0;
end;

constructor TDay.Create(aDate: TDateTime);
begin
  fDate := aDate;
  fWhatHappenedAdditionalyToTheTasks := '';
  fBreakfast := '';
  fLunch := '';
  fBrunch := '';
  fTeeCoffeeTime := '';
  fDinner := '';
  fTemperatureAtMorning := 0;
  fPulseAtMorning := 0;
  fHeartArrhythmiaSymbolAppearsAtMorning := FALSE;
  fBloodPressureSysAtMorning := 0;
  fBloodPressureDiaAtMorning := 0;
  fOxygenSaturationAtMorning := 0;
  fGlucoseLevelAtMorning := 0;
  fWeightAtMorning := 0;
  fTemperatureAtLunch := 0;
  fPulseAtLunch := 0;
  fHeartArrhythmiaSymbolAppearsAtLunch := FALSE;
  fBloodPressureSysAtLunch := 0;
  fBloodPressureDiaAtLunch := 0;
  fOxygenSaturationAtLunch := 0;
  fGlucoseLevelAtLunch := 0;
  fWeightAtLunch := 0;
  fTemperatureAtEvening := 0;
  fPulseAtEvening := 0;
  fHeartArrhythmiaSymbolAppearsAtEvening := FALSE;
  fBloodPressureSysAtEvening := 0;
  fBloodPressureDiaAtEvening := 0;
  fOxygenSaturationAtEvening := 0;
  fGlucoseLevelAtEvening := 0;
  fWeightAtEvening := 0;
  fHealthCondition := '';
  fWeatherHumidity := 0;
  fWeatherMoonPhase := '';
  fWeatherPressure := 0;
  fWeatherTemperatureAfternoon := 0;
  fWeatherTemperatureEvening := 0;
  fWeatherTemperatureMorning := 0;
  fWeatherTemperatureOvernight := 0;
  fWeatherUVIndex := 0;
  fWeatherWindDirection := '';
  fWeatherWindSpeed := 0;
  fWeather := '';
  fThoughts := '';
  SetLength(fPicture, 0);
  fLastTaskID := 0;
  fTasks := TObjectList<TTask>.Create;
  fTasks.OwnsObjects := True;
  fLastConversationID := 0;
  fConversations := TObjectList<TConversation>.Create;
  fConversations.OwnsObjects := True;
  fLastShoppingID := 0;
  fShoppings := TObjectList<TShopping>.Create;
  fShoppings.OwnsObjects := True;
end;

destructor TDay.Destroy;
begin
  FreeAndNil(fConversations);
  inherited;
end;

procedure TDay.SetEmptyPicture;
begin
  SetLength(fPicture, 0);
end;

constructor TDiary.Create;
begin
  fCopyright := 'Copyright © 2023 - 2025 Sven Dmitrienko';
  fDB := TObjectList<TDay>.Create;
  fDB.OwnsObjects := True;
  fVersion := FILE_VERSION;
end;

destructor TDiary.Destroy;
begin
  FreeAndNil(fDB);
  inherited;
end;

function TDiary.GetDay(aDate: TDateTime): TDay;
var
  i: integer;
  a_Day, a_Day2: TDay;
  a_Found: Boolean;
begin
  a_Day := nil;
  a_Day2 := TDay.Create(aDate);
  a_Found := False;
  if (fDB.Count > 0) then
    for i := 0 to fDB.Count - 1 do
    begin
      a_Day := fDB.Items[i];
      if (SameDate(a_Day.fDate, aDate))then
      begin
        a_Found := True;
        Break;
      end;
    end;
  if (a_Found) then
  begin
    if (Assigned(a_Day)) then
    begin
      FreeAndNil(a_Day2);
      a_Day2 := a_Day;
    end;
  end
  else
  begin
    fDB.Add(a_Day2);
    fDB.Sort(TComparer<TDay>.Construct(
        function (const Left, Right: TDay): Integer
        begin
          Result := CompareDate(Left.Date, Right.Date);
        end
      )
    );
  end;
  Result := a_Day2;
end;

constructor TTaskOfTheDay.Create;
begin
  fStartDateTime := Now;
  fEndDateTime := Now;
  fTask := '';
  fNotice := '';
end;

end.
