unit FormMain;

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
  EditBtn, Menus, TAGraph, TASeries, Generics.Collections, Generics.Defaults,
  DateUtils, Ean, Translator, ApplicationInfo, RegistryEx, PersistentForm,
  Theme, Common, XML, EdcProject;

type

  TPeriod = (prDay, prWeek, prMonth, prYear);
  TValueUnit = (vukWh, vuWh, vukW, vuW);

  { TFormMain }

  TFormMain = class(TForm)
    ApplicationInfo1: TApplicationInfo;
    ButtonIntervalRight: TButton;
    ButtonIntervalLeft: TButton;
    ButtonIntervalRightMax: TButton;
    ButtonIntervalLeftMin: TButton;
    Chart1: TChart;
    Chart1LineSeries1: TLineSeries;
    Chart1LineSeries2: TLineSeries;
    Chart1LineSeries3: TLineSeries;
    Chart1LineSeries4: TLineSeries;
    Chart1LineSeries5: TLineSeries;
    Chart1LineSeries6: TLineSeries;
    CheckBoxShowResult: TCheckBox;
    ComboBoxEan: TComboBox;
    ComboBoxEan3: TComboBox;
    ComboBoxEanData: TComboBox;
    ComboBoxEan2: TComboBox;
    ComboBoxPeriod: TComboBox;
    ComboBoxUnit: TComboBox;
    DateEdit1: TDateEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    ListViewOverview: TListView;
    ListViewData: TListView;
    ListViewSpotPrices: TListView;
    MainMenu1: TMainMenu;
    Memo1: TMemo;
    MenuItemRemove: TMenuItem;
    MenuItemLoad: TMenuItem;
    MenuItemSave: TMenuItem;
    MenuItemTools: TMenuItem;
    MenuItemImportReports: TMenuItem;
    MenuItemImportSpotPrices: TMenuItem;
    MenuItemFile: TMenuItem;
    PageControl1: TPageControl;
    PersistentForm1: TPersistentForm;
    PopupMenuOverview: TPopupMenu;
    TabSheetSpotPrices: TTabSheet;
    TabSheetOverview: TTabSheet;
    TabSheetData: TTabSheet;
    TabSheetChart: TTabSheet;
    TabSheetLog: TTabSheet;
    ThemeManager1: TThemeManager;
    TimeEdit1: TTimeEdit;
    Translator1: TTranslator;
    procedure ButtonIntervalLeftClick(Sender: TObject);
    procedure ButtonIntervalLeftMinClick(Sender: TObject);
    procedure ButtonIntervalRightClick(Sender: TObject);
    procedure ButtonIntervalRightMaxClick(Sender: TObject);
    procedure CheckBoxShowResultChange(Sender: TObject);
    procedure ComboBoxEanDataSelect(Sender: TObject);
    procedure ComboBoxEanSelect(Sender: TObject);
    procedure ComboBoxPeriodSelect(Sender: TObject);
    procedure ComboBoxUnitSelect(Sender: TObject);
    procedure DateEdit1Change(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure MenuItemImportReportsClick(Sender: TObject);
    procedure MenuItemImportSpotPricesClick(Sender: TObject);
    procedure MenuItemLoadClick(Sender: TObject);
    procedure MenuItemRemoveClick(Sender: TObject);
    procedure MenuItemSaveClick(Sender: TObject);
    procedure TabSheetOverviewShow(Sender: TObject);
    procedure TabSheetChartShow(Sender: TObject);
    procedure TabSheetDataShow(Sender: TObject);
    procedure TabSheetLogShow(Sender: TObject);
    procedure TabSheetSpotPricesShow(Sender: TObject);
    procedure TimeEdit1Change(Sender: TObject);
    procedure Translator1Translate(Sender: TObject);
  private
    IntervalFrom: TDateTime;
    IntervalTo: TDateTime;
    ValueUnit: TValueUnit;
    Period: TPeriod;
    ReportsDir: string;
    SpotPricesDir: string;
    ProjectFileName: string;
    ShowResult: Boolean;
    EdcProject: TEdcProject;
    function MeasureToFloat(Value: Double; Interval: Double): Double;
    function MeasureToStr(Value: Double): string;
    procedure LoadConfig;
    procedure Report;
    procedure ReloadListViewOverview;
    procedure ReloadListViewData;
    procedure ReloadListViewSpotPrices;
    procedure ReloadChart;
    function GetIntervalLength: TDateTime;
    function GetIntervalStep: TDateTime;
    procedure SaveConfig;
    procedure UpdateInterface;
    procedure UpdateInterval;
    procedure ShowActiveTab;
  public
  end;


var
  FormMain: TFormMain;


implementation

{$R *.lfm}

resourcestring
  SEAN = 'EAN';
  SOwner = 'Owner';
  SShared = 'Shared';
  SMeasured = 'Measured';
  SResult = 'Result';
  SDay = 'Day';
  SWeek = 'Week';
  SMonth = 'Month';
  SYear = 'Year';

{ TFormMain }

procedure TFormMain.CheckBoxShowResultChange(Sender: TObject);
begin
  if CheckBoxShowResult.Checked <> ShowResult then begin
    ShowResult := CheckBoxShowResult.Checked;
    ReloadChart;
  end;
end;

procedure TFormMain.ComboBoxEanDataSelect(Sender: TObject);
begin
  ReloadListViewData;
end;

procedure TFormMain.ButtonIntervalRightClick(Sender: TObject);
begin
  IntervalTo := IntervalTo + GetIntervalLength;
  UpdateInterval;
end;

procedure TFormMain.ButtonIntervalRightMaxClick(Sender: TObject);
begin
  IntervalTo := EdcProject.Eans.GetMaxTime + FifteenMinute;
  UpdateInterval;
end;

procedure TFormMain.ButtonIntervalLeftClick(Sender: TObject);
begin
  IntervalTo := IntervalTo - GetIntervalLength;
  UpdateInterval;
end;

procedure TFormMain.ButtonIntervalLeftMinClick(Sender: TObject);
begin
  IntervalTo := EdcProject.Eans.GetMinTime + GetIntervalLength + FifteenMinute;
  UpdateInterval;
end;

procedure TFormMain.ComboBoxEanSelect(Sender: TObject);
begin
  ReloadChart;
end;

procedure TFormMain.ComboBoxPeriodSelect(Sender: TObject);
begin
  Period := TPeriod(ComboBoxPeriod.ItemIndex);
  UpdateInterval;
end;

procedure TFormMain.ComboBoxUnitSelect(Sender: TObject);
begin
  ValueUnit := TValueUnit(ComboBoxUnit.ItemIndex);
  ShowActiveTab;
end;

procedure TFormMain.DateEdit1Change(Sender: TObject);
var
  NewIntervalTo: TDateTime;
begin
  NewIntervalTo := DateEdit1.Date + TimeOf(IntervalTo);
  if NewIntervalTo <> IntervalTo then begin
    IntervalTo := NewIntervalTo;
    UpdateInterval;
  end;
end;

procedure TFormMain.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
end;

procedure TFormMain.FormCreate(Sender: TObject);
begin
  PageControl1.TabIndex := 0;
  EdcProject := TEdcProject.Create;
  LoadConfig;
end;

procedure TFormMain.FormDestroy(Sender: TObject);
begin
  SaveConfig;
  FreeAndNil(EdcProject);
end;

procedure TFormMain.FormShow(Sender: TObject);
begin
  EdcProject.LoadFromFile(ProjectFileName);

  UpdateInterval;
  UpdateInterface;
end;

procedure TFormMain.MenuItemImportReportsClick(Sender: TObject);
begin
  EdcProject.ImportReports(ReportsDir);

  if (EdcProject.Eans.Count > 0) and (EdcProject.Eans[0].Values.Count > 0) then
    IntervalTo := EdcProject.Eans[0].Values.Last.Time + FifteenMinute;
  UpdateInterval;
  UpdateInterface;
end;

procedure TFormMain.MenuItemImportSpotPricesClick(Sender: TObject);
begin
  //EdcProject.SpotPrices.Import(SpotPricesDir);
  EdcProject.SpotPrices.LoadFromWeb;

  ShowActiveTab;
end;

procedure TFormMain.MenuItemLoadClick(Sender: TObject);
begin
  EdcProject.LoadFromFile(ProjectFileName);

  if (EdcProject.Eans.Count > 0) and (EdcProject.Eans[0].Values.Count > 0) then
    IntervalTo := EdcProject.Eans[0].Values.Last.Time + FifteenMinute;
  UpdateInterval;
  UpdateInterface;
end;

procedure TFormMain.MenuItemRemoveClick(Sender: TObject);
begin
  if Assigned(ListViewOverview.Selected) then
    EdcProject.Eans.Remove(ListViewOverview.Selected.Data);
  ReloadListViewOverview;
end;

procedure TFormMain.MenuItemSaveClick(Sender: TObject);
begin
  EdcProject.SaveToFile(ProjectFileName);
end;

procedure TFormMain.TabSheetOverviewShow(Sender: TObject);
begin
  ReloadListViewOverview;
end;

procedure TFormMain.TabSheetChartShow(Sender: TObject);
begin
  EdcProject.Eans.LoadToStrings(ComboBoxEan.Items, True);
  if (ComboBoxEan.Items.Count > 1) and (ComboBoxEan.ItemIndex = -1) then
    ComboBoxEan.ItemIndex := 1;
  EdcProject.Eans.LoadToStrings(ComboBoxEan2.Items, True);
  EdcProject.Eans.LoadToStrings(ComboBoxEan3.Items, True);
  ReloadChart;
end;

procedure TFormMain.TabSheetDataShow(Sender: TObject);
begin
  EdcProject.Eans.LoadToStrings(ComboBoxEanData.Items);
  if (ComboBoxEanData.Items.Count > 0) and (ComboBoxEanData.ItemIndex = -1) then
    ComboBoxEanData.ItemIndex := 0;
  ReloadListViewData;
end;

procedure TFormMain.TabSheetLogShow(Sender: TObject);
begin
  Report;
end;

procedure TFormMain.TabSheetSpotPricesShow(Sender: TObject);
begin
  ReloadListViewSpotPrices;
end;

procedure TFormMain.TimeEdit1Change(Sender: TObject);
var
  NewIntervalTo: TDateTime;
begin
  NEwIntervalTo := DateOf(IntervalTo) + TimeEdit1.Time;
  if NewIntervalTo <> IntervalTo then begin
    IntervalTo := NewIntervalTo;
    UpdateInterval;
  end;
end;

procedure TFormMain.Translator1Translate(Sender: TObject);
begin
  ComboBoxPeriod.Items[Integer(prDay)] := SDay;
  ComboBoxPeriod.Items[Integer(prWeek)] := SWeek;
  ComboBoxPeriod.Items[Integer(prMonth)] := SMonth;
  ComboBoxPeriod.Items[Integer(prYear)] := SYear;
  Ean.Translate;
end;

function TFormMain.MeasureToFloat(Value: Double; Interval: Double): Double;
begin
  case ValueUnit of
    vukWh: Result := Value;
    vuWh: Result := Value * 1000;
    vukW: Result := Value / Interval;
    vuW: Result := Value / Interval * 1000;
    else Result := 0;
  end;
end;

function TFormMain.MeasureToStr(Value: Double): string;
begin
  Result := CurrToStr(MeasureToFloat(Value, GetIntervalLength * 24));
end;

procedure TFormMain.Report;
var
  I: Integer;
  TotalIn, TotalOut: Double;
begin
  Memo1.Lines.BeginUpdate;
  try
    Memo1.Lines.Clear;
    for I := 0 to EdcProject.Eans.Count - 1 do
    with EdcProject.Eans[I] do begin
      Memo1.Lines.Add(SEAN + ': ' + Number);
      Memo1.Lines.Add(SOwner + ': ' + Owner);
      TotalIn := GetTotalIn(IntervalFrom, IntervalTo);
      TotalOut := GetTotalOut(IntervalFrom, IntervalTo);
      Memo1.Lines.Add(SMeasured + ': ' + IntToStr(Trunc(TotalIn)));
      Memo1.Lines.Add(SResult + ': ' + IntToStr(Trunc(TotalOut)));
      if TotalIn <> 0 then
      Memo1.Lines.Add(SShared + ': ' + IntToStr(Trunc(GetSharedPercent(IntervalFrom, IntervalTo))) + ' %');
      Memo1.Lines.Add('');
    end;
  finally
    Memo1.Lines.EndUpdate;
  end;
end;

procedure TFormMain.ReloadListViewOverview;
var
  ListItem: TListItem;
  I: Integer;
begin
  ListViewOverview.BeginUpdate;
  try
    ListViewOverview.Items.Clear;
    for I := 0 to EdcProject.Eans.Count - 1 do
    with EdcProject.Eans[I] do begin
      ListItem := ListViewOverview.Items.Add;
      ListItem.Caption := Number;
      ListItem.Data := EdcProject.Eans[I];
      ListItem.SubItems.Add(Owner);
      ListItem.SubItems.Add(Address);
      ListItem.SubItems.Add(EanKindText[Kind]);
      ListItem.SubItems.Add(MeasureToStr(GetTotalIn(IntervalFrom, IntervalTo)));
      ListItem.SubItems.Add(MeasureToStr(GetShared(IntervalFrom, IntervalTo)));
      ListItem.SubItems.Add(IntToStr(Trunc(GetSharedPercent(IntervalFrom, IntervalTo))));
      ListItem.SubItems.Add(FloatToStr(PriceLow));
      ListItem.SubItems.Add(FloatToStr(PriceHigh));
      ListItem.SubItems.Add(FloatToStr(PriceSpot));
      ListItem.SubItems.Add(CurrToStr(GetPrice(IntervalFrom, IntervalTo, EdcProject.SpotPrices, Low(Integer))));
      ListItem.SubItems.Add(CurrToStr(GetSavings(IntervalFrom, IntervalTo, EdcProject.SpotPrices)));
      ListItem.SubItems.Add(DistributionTariff);
      ListItem.SubItems.Add(CurrToStr(GetPrice(IntervalFrom, IntervalTo, EdcProject.SpotPrices, 0)));
    end;
  finally
    ListViewOverview.EndUpdate;
  end;
end;

procedure TFormMain.ReloadListViewData;
var
  ListItem: TListItem;
  I: Integer;
  Ean: TEan;
begin
  ListViewData.Items.Clear;
  if ComboBoxEanData.ItemIndex = -1 then Exit;
  Ean := TEan(ComboBoxEanData.Items.Objects[ComboBoxEanData.ItemIndex]);

  if Assigned(Ean) then begin
    ListViewData.BeginUpdate;
    try
      for I := 0 to Ean.Values.Count - 1 do
      with Ean.Values[I] do
      if (Time >= IntervalFrom) and (Time < IntervalTo) then begin
        ListItem := ListViewData.Items.Add;
        ListItem.Caption := DateTimeToStr(Time);
        ListItem.SubItems.Add(FloatToStr(ValueIn));
        ListItem.SubItems.Add(FloatToStr(ValueOut));
        ListItem.SubItems.Add(IntToStr(Trunc(GetShared)));
      end;
    finally
      ListViewData.EndUpdate;
    end;
  end;
end;

procedure TFormMain.ReloadListViewSpotPrices;
var
  ListItem: TListItem;
  I: Integer;
begin
  ListViewSpotPrices.Items.Clear;

  ListViewSpotPrices.BeginUpdate;
  try
    for I := 0 to EdcProject.SpotPrices.Count - 1 do
    with EdcProject.SpotPrices[I] do
    if (Time >= IntervalFrom) and (Time < IntervalTo) then
    begin
      ListItem := ListViewSpotPrices.Items.Add;
      ListItem.Caption := DateTimeToStr(Time);
      ListItem.SubItems.Add(FloatToStr(Value));
    end;
  finally
    ListViewSpotPrices.EndUpdate;
  end;
end;

procedure TFormMain.ReloadChart;
var
  I: Integer;
  Ean: TEan;
begin
  Chart1LineSeries1.BeginUpdate;
  Chart1LineSeries4.BeginUpdate;
  Chart1LineSeries1.Clear;
  Chart1LineSeries4.Clear;
  if ComboBoxEan.ItemIndex <> -1 then begin
    Ean := TEan(ComboBoxEan.Items.Objects[ComboBoxEan.ItemIndex]);
    if Assigned(Ean) then
    with Ean do begin
      for I := 0 to Values.Count - 1 do
        if (Values[I].Time >= IntervalFrom) and (Values[I].Time < IntervalTo) then begin
          Chart1LineSeries1.AddXY(Values[I].Time, MeasureToFloat(Values[I].ValueIn, 1 / 4));
          if ShowResult then Chart1LineSeries4.AddXY(Values[I].Time, MeasureToFloat(Values[I].ValueOut, 1 / 4));
        end;
    end;
  end;
  Chart1LineSeries1.EndUpdate;
  Chart1LineSeries4.EndUpdate;

  Chart1LineSeries2.BeginUpdate;
  Chart1LineSeries5.BeginUpdate;
  Chart1LineSeries2.Clear;
  Chart1LineSeries5.Clear;
  if ComboBoxEan2.ItemIndex <> -1 then begin
    Ean := TEan(ComboBoxEan2.Items.Objects[ComboBoxEan2.ItemIndex]);
    if Assigned(Ean) then
    with Ean do begin
      for I := 0 to Values.Count - 1 do
        if (Values[I].Time >= IntervalFrom) and (Values[I].Time < IntervalTo) then begin
          Chart1LineSeries2.AddXY(Values[I].Time, MeasureToFloat(Values[I].ValueIn, 1 / 4));
          if ShowResult then Chart1LineSeries5.AddXY(Values[I].Time, MeasureToFloat(Values[I].ValueOut, 1 / 4));
        end;
    end;
  end;
  Chart1LineSeries2.EndUpdate;
  Chart1LineSeries5.EndUpdate;

  Chart1LineSeries3.BeginUpdate;
  Chart1LineSeries6.BeginUpdate;
  Chart1LineSeries3.Clear;
  Chart1LineSeries6.Clear;
  if ComboBoxEan3.ItemIndex <> -1 then begin
    Ean := TEan(ComboBoxEan3.Items.Objects[ComboBoxEan3.ItemIndex]);
    if Assigned(Ean) then
    with Ean do begin
      for I := 0 to Values.Count - 1 do
        if (Values[I].Time >= IntervalFrom) and (Values[I].Time < IntervalTo) then begin
          Chart1LineSeries3.AddXY(Values[I].Time, MeasureToFloat(Values[I].ValueIn, 1 / 4));
          if ShowResult then Chart1LineSeries6.AddXY(Values[I].Time, MeasureToFloat(Values[I].ValueOut, 1 / 4));
        end;
    end;
  end;
  Chart1LineSeries3.EndUpdate;
  Chart1LineSeries6.EndUpdate;
end;

function TFormMain.GetIntervalLength: TDateTime;
begin
  case Period of
    prDay: Result := 1;
    prWeek: Result := 7;
    prMonth: Result := 31;
    prYear: Result := 365;
  end;
end;

function TFormMain.GetIntervalStep: TDateTime;
begin
  case Period of
    prDay: Result := FifteenMinute;
    prWeek: Result := 1;
    prMonth: Result := 1;
    prYear: Result := 30;
  end;
end;

procedure TFormMain.UpdateInterface;
begin
  ComboBoxUnit.ItemIndex := Integer(ValueUnit);
  ComboBoxPeriod.ItemIndex := Integer(Period);
  CheckBoxShowResult.Checked := ShowResult;
end;

procedure TFormMain.UpdateInterval;
begin
  IntervalFrom := IntervalTo - GetIntervalLength;
  DateEdit1.Date := IntervalTo;
  TimeEdit1.Time := IntervalTo;
  ShowActiveTab;
end;

procedure TFormMain.ShowActiveTab;
begin
  if Assigned(PageControl1.ActivePage.OnShow) then
    PageControl1.ActivePage.OnShow(nil);
end;

procedure TFormMain.LoadConfig;
begin
  PersistentForm1.RegistryContext := ApplicationInfo1.GetRegistryContext;

  with TRegistryEx.Create do
  try
    CurrentContext := ApplicationInfo1.GetRegistryContext;
    if ValueExists('LanguageCode') then
      Translator1.Language := Translator1.Languages.SearchByCode(ReadStringWithDefault('LanguageCode', ''))
      else Translator1.Language := Translator1.Languages.SearchByCode('');
    if ValueExists('Theme') then
      ThemeManager1.Theme := ThemeManager1.Themes.FindByName(ReadStringWithDefault('Theme', 'System'))
      else ThemeManager1.Theme := ThemeManager1.Themes.FindByName('System');
    ValueUnit := TValueUnit(ReadIntegerWithDefault('Unit', Integer(ValueUnit)));
    Period := TPeriod(ReadIntegerWithDefault('Period', Integer(Period)));
    ReportsDir := ReadStringWithDefault('ReportsDir', ReportsDir);
    SpotPricesDir := ReadStringWithDefault('SpotPricesDir', SpotPricesDir);
    ProjectFileName := ReadStringWithDefault('ProjectFileName', ProjectFileName);
    PageControl1.TabIndex := ReadIntegerWithDefault('ActiveTab', PageControl1.TabIndex);
    ShowResult := ReadBoolWithDefault('ShowResult', ShowResult);
    IntervalFrom := ReadDateTimeWithDefault('IntervalFrom', IntervalFrom);
    IntervalTo := ReadDateTimeWithDefault('IntervalTo', IntervalTo);
  finally
    Free;
  end;
end;

procedure TFormMain.SaveConfig;
begin
  with TRegistryEx.Create do
  try
    CurrentContext := ApplicationInfo1.GetRegistryContext;
    if Assigned(Translator1.Language) and (Translator1.Language.Code <> '') then
      WriteString('LanguageCode', Translator1.Language.Code)
      else DeleteValue('LanguageCode');
    if Assigned(ThemeManager1.Theme) and (ThemeManager1.Theme.Name <> '') then
      WriteString('Theme', ThemeManager1.Theme.Name)
      else DeleteValue('Theme');
    WriteInteger('Unit', Integer(ValueUnit));
    WriteInteger('Period', Integer(Period));
    WriteString('ReportsDir', ReportsDir);
    WriteString('SpotPricesDir', SpotPricesDir);
    WriteString('ProjectFileName', ProjectFileName);
    WriteInteger('ActiveTab', PageControl1.TabIndex);
    WriteBool('ShowResult', ShowResult);
    WriteDateTime('IntervalFrom', IntervalFrom);
    WriteDateTime('IntervalTo', IntervalTo);
  finally
    Free;
  end;
end;

end.

