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, SpotPrice, Clipbrd;

type

  TPeriod = (prHour, prDay, prWeek, prMonth, prYear);

  { 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;
    MenuItemCopyOverview: TMenuItem;
    MenuItemCopy: TMenuItem;
    MenuItemModify: TMenuItem;
    MenuItemAdd: TMenuItem;
    MenuItemRemove: TMenuItem;
    MenuItemLoad: TMenuItem;
    MenuItemSave: TMenuItem;
    MenuItemTools: TMenuItem;
    MenuItemImportReports: TMenuItem;
    MenuItemImportSpotPrices: TMenuItem;
    MenuItemFile: TMenuItem;
    PageControl1: TPageControl;
    PersistentForm1: TPersistentForm;
    PopupMenuData: TPopupMenu;
    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 MenuItemAddClick(Sender: TObject);
    procedure MenuItemCopyClick(Sender: TObject);
    procedure MenuItemCopyOverviewClick(Sender: TObject);
    procedure MenuItemImportReportsClick(Sender: TObject);
    procedure MenuItemImportSpotPricesClick(Sender: TObject);
    procedure MenuItemLoadClick(Sender: TObject);
    procedure MenuItemModifyClick(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
    Interval: TInterval;
    ValueUnit: TValueUnit;
    Period: TPeriod;
    ReportsDir: string;
    SpotPricesDir: string;
    ProjectFileName: string;
    ShowResult: Boolean;
    EdcProject: TEdcProject;
    procedure CopyListView(ListView: TListView);
    procedure LoadConfig;
    procedure Report;
    procedure ReloadListViewOverview;
    procedure ReloadListViewData;
    procedure ReloadListViewSpotPrices;
    procedure ReloadChartSeries(Ean: TEan; SeriesValueIn: TLineSeries;
      SeriesValueOut: TLineSeries);
    procedure ReloadChart;
    function GetIntervalLength: TDateTime;
    function GetIntervalStep: TDateTime;
    procedure SaveConfig;
    procedure UpdateInterface;
    procedure UpdateInterval;
    procedure ShowActiveTab;
  public
  end;

var
  FormMain: TFormMain;


implementation

{$R *.lfm}

uses
  FormEan;

resourcestring
  SEAN = 'EAN';
  SOwner = 'Owner';
  SShared = 'Shared';
  SMeasured = 'Measured';
  SResult = 'Result';
  SHour = 'Hour';
  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
  Interval.TimeTo := Interval.TimeTo + GetIntervalLength;
  UpdateInterval;
end;

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

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

procedure TFormMain.ButtonIntervalLeftMinClick(Sender: TObject);
begin
  Interval.TimeTo := 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(Interval.TimeTo);
  if NewIntervalTo <> Interval.TimeTo then begin
    Interval.TimeTo := 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);
var
  I: TValueUnit;
begin
  EdcProject.LoadFromFile(ProjectFileName);

  ComboBoxUnit.Items.BeginUpdate;
  ComboBoxUnit.Items.Clear;
  try
    for I := Low(TValueUnit) to High(TValueUnit) do
      ComboBoxUnit.Items.Add(ValueUnitText[I]);
  finally
    ComboBoxUnit.Items.EndUpdate;
  end;

  UpdateInterval;
  UpdateInterface;
end;

procedure TFormMain.MenuItemAddClick(Sender: TObject);
var
  FormEan: TFormEan;
  Ean: TEan;
begin
  FormEan := TFormEan.Create(nil);
  if FormEan.ShowModal = mrOk then begin
    Ean := TEan.Create;
    FormEan.SaveData(Ean);
    EdcProject.Eans.Add(Ean);
    ReloadListViewOverview;
  end;
  FormEan.Free;
end;

procedure TFormMain.MenuItemCopyClick(Sender: TObject);
begin
  CopyListView(ListViewData);
end;

procedure TFormMain.MenuItemCopyOverviewClick(Sender: TObject);
begin
  CopyListView(ListViewOverview);
end;

procedure TFormMain.CopyListView(ListView: TListView);
var
  Text: string;
  I: Integer;
  J: Integer;
  Line: string;
begin
  Text := '';
  for I := 0 to ListView.Items.Count - 1 do
    if ListView.Items[I].Selected then
    with ListView.Items[I] do begin
      Line := Caption + #9;
      for J := 0 to SubItems.Count - 1 do
        Line := Line + SubItems[J] + #9;
      Text := Text + Line + LineEnding;
    end;
  Clipboard.AsText := Text;
end;

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

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

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

  EdcProject.SortEansByTime;

  ShowActiveTab;
end;

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

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

procedure TFormMain.MenuItemModifyClick(Sender: TObject);
var
  FormEan: TFormEan;
begin
  FormEan := TFormEan.Create(nil);
  if not Assigned(ListViewOverview.Selected) then Exit;
  FormEan.LoadData(TEan(ListViewOverview.Selected.Data));
  if FormEan.ShowModal = mrOk then begin
    FormEan.SaveData(TEan(ListViewOverview.Selected.Data));
    ReloadListViewOverview;
  end;
  FormEan.Free;
end;

procedure TFormMain.MenuItemRemoveClick(Sender: TObject);
begin
  if Assigned(ListViewOverview.Selected) then begin
    EdcProject.Eans.Remove(ListViewOverview.Selected.Data);
    ReloadListViewOverview;
  end;
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(Interval.TimeTo) + TimeEdit1.Time;
  if NewIntervalTo <> Interval.TimeTo then begin
    Interval.TimeTo := NewIntervalTo;
    UpdateInterval;
  end;
end;

procedure TFormMain.Translator1Translate(Sender: TObject);
begin
  ComboBoxPeriod.Items[Integer(prHour)] := SHour;
  ComboBoxPeriod.Items[Integer(prDay)] := SDay;
  ComboBoxPeriod.Items[Integer(prWeek)] := SWeek;
  ComboBoxPeriod.Items[Integer(prMonth)] := SMonth;
  ComboBoxPeriod.Items[Integer(prYear)] := SYear;
  Ean.Translate;
  Translate;
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(Interval, ValueUnit);
      TotalOut := GetTotalOut(Interval, ValueUnit);
      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(Interval, ValueUnit))) + ' %');
      Memo1.Lines.Add('');
    end;
  finally
    Memo1.Lines.EndUpdate;
  end;
end;

procedure TFormMain.ReloadListViewOverview;
var
  ListItem: TListItem;
  I: Integer;
  TotalIn: Currency;
  TotalOut: Currency;
  TotalShared: Currency;
  SharedPercent: Double;
begin

  ListViewOverview.BeginUpdate;
  try
    ListViewOverview.Items.Clear;
    for I := 0 to EdcProject.Eans.Count - 1 do
    with EdcProject.Eans[I] do begin
      TotalIn := GetTotalIn(Interval, ValueUnit);
      TotalOut := GetTotalOut(Interval, ValueUnit);
      TotalShared := TotalIn - TotalOut;
      if TotalIn > 0 then
        SharedPercent := (1 - TotalOut / TotalIn) * 100
        else SharedPercent := 0;

      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(CurrToStr(TotalIn));
      ListItem.SubItems.Add(CurrToStr(TotalOut));
      ListItem.SubItems.Add(CurrToStr(TotalShared));
      ListItem.SubItems.Add(IntToStr(Trunc(SharedPercent)));
      ListItem.SubItems.Add(CurrToStr(GetTotalInMinPrice(Interval, ValueUnit, PriceSpot)));
      ListItem.SubItems.Add(FloatToStr(PriceLow));
      ListItem.SubItems.Add(FloatToStr(PriceHigh));
      ListItem.SubItems.Add(FloatToStr(PriceSpot));
      ListItem.SubItems.Add(DistributionTariff);
    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.Time >= Interval.TimeFrom) and (Time.Time < Interval.TimeTo) then begin
        ListItem := ListViewData.Items.Add;
        ListItem.Caption := DateTimeToStr(Time.Time);
        ListItem.SubItems.Add(FloatToStr(ValueIn));
        ListItem.SubItems.Add(FloatToStr(ValueOut));
        ListItem.SubItems.Add(IntToStr(Trunc(GetShared)));
        ListItem.SubItems.Add(FloatToStr(Time.Value));
        ListItem.SubItems.Add(FloatToStr(Time.Value * Wat));
      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 >= Interval.TimeFrom) and (Time < Interval.TimeTo) then
    begin
      ListItem := ListViewSpotPrices.Items.Add;
      ListItem.Caption := DateTimeToStr(Time);
      ListItem.SubItems.Add(FloatToStr(Value));
    end;
  finally
    ListViewSpotPrices.EndUpdate;
  end;
end;

procedure TFormMain.ReloadChartSeries(Ean: TEan; SeriesValueIn: TLineSeries; SeriesValueOut: TLineSeries);
var
  I: Integer;
begin
  SeriesValueIn.BeginUpdate;
  SeriesValueOut.BeginUpdate;
  try
    SeriesValueIn.Clear;
    SeriesValueOut.Clear;
    if Assigned(Ean) then
    with Ean do begin
      for I := 0 to Values.Count - 1 do
        if (Values[I].Time.Time >= Interval.TimeFrom) and
          (Values[I].Time.Time < Interval.TimeTo) then begin
          SeriesValueIn.AddXY(Values[I].Time.Time, Values[I].GetValueIn(ValueUnit, Ean));
          if ShowResult then
            SeriesValueOut.AddXY(Values[I].Time.Time, Values[I].GetValueOut(ValueUnit, Ean));
        end;
    end;
  finally
    SeriesValueIn.EndUpdate;
    SeriesValueOut.EndUpdate;
  end;
end;

procedure TFormMain.ReloadChart;
var
  Ean: TEan;
begin
  if ComboBoxEan.ItemIndex <> -1 then begin
    Ean := TEan(ComboBoxEan.Items.Objects[ComboBoxEan.ItemIndex]);
    ReloadChartSeries(Ean, Chart1LineSeries1, Chart1LineSeries4);
  end;

  if ComboBoxEan2.ItemIndex <> -1 then begin
    Ean := TEan(ComboBoxEan2.Items.Objects[ComboBoxEan2.ItemIndex]);
    ReloadChartSeries(Ean, Chart1LineSeries2, Chart1LineSeries5);
  end;

  if ComboBoxEan3.ItemIndex <> -1 then begin
    Ean := TEan(ComboBoxEan3.Items.Objects[ComboBoxEan3.ItemIndex]);
    ReloadChartSeries(Ean, Chart1LineSeries3, Chart1LineSeries6);
  end;
end;

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

function TFormMain.GetIntervalStep: TDateTime;
begin
  case Period of
    prHour: Result := OneMinute;
    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
  Interval.TimeFrom := Interval.TimeTo - GetIntervalLength;
  DateEdit1.Date := Interval.TimeTo;
  TimeEdit1.Time := Interval.TimeTo;
  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);
    Interval.TimeFrom := ReadDateTimeWithDefault('IntervalFrom', Interval.TimeFrom);
    Interval.TimeTo := ReadDateTimeWithDefault('IntervalTo', Interval.TimeTo);
  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', Interval.TimeFrom);
    WriteDateTime('IntervalTo', Interval.TimeTo);
  finally
    Free;
  end;
end;

end.

