unit MotohrPanel;

interface
uses
  HyperStr,
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Buttons, StdCtrls, ComCtrls, ExtCtrls, ImgList;


type
  PCounterRec = ^TCounterRec;
  TCounterRec = record
    tagidx: integer;
    sid: string;
    descr: string;
    timer: Boolean;
    total: Boolean;
    lbDescr: TLabel;
    lbValue: TLabel;
    sec: Integer;
  end;

  TMotohrPanel = class
  private
    pnl: TPanel;
    machDescr: string;
    machName: string;
    tagSystemTime: Integer;
    tagMachTime: Integer;
    counters: TList;

    procedure createLabels(pnl: TPanel; p: PCounterRec);
    procedure freeLabels(p: PCounterRec);
    procedure removeCounter(index: integer);
    procedure labelClick(Sender: TObject);
//    procedure splitDescr(descr: string; var descrShort, descrLong: string);
    procedure lbDescrClick(Sender: TObject);
    procedure updateCounterTops;
  public
    constructor Create;
    destructor Destroy; override;
    procedure init(pnl: TPanel; machName: string; machdescr: string);
    procedure updateValues;
    procedure toggleFolded;
  end;


implementation
uses
  Users,
  main,
  Motohr,
  MotohrLogbook,
  MotohrMessage,
  MotohrDb,
  DataMod,
  MesLogging,
  InputDialog,
  InfoDlg,
  TagStorage,
  RpVisualGlobal,
  RpVisualParams,
  RpVisualUtils, StrUtils;


var
  folded: boolean;

constructor TMotohrPanel.Create;
begin
  counters := TList.Create;
end;


destructor TMotohrPanel.Destroy;
begin
  while counters.Count > 0 do
    removeCounter(0);

  counters.Free;
  inherited;
end;


procedure TMotohrPanel.init(pnl: TPanel; machName: string; machdescr: string);
  function cmp(a, b: PCounterRec): Integer;
  begin
    result := iif(b.total, 1, 0) - iif(a.total, 1, 0);
    if result = 0 then begin
      result := iif(a.timer, 1, 0) - iif(b.timer, 1, 0);
      if result = 0 then begin
        Result := AnsiStrIComp( PChar(a.descr), PChar(b.descr) )
      end;
    end;
  end;

var
  smach: string;
  scnt: string;
  tagname: string;
  i: integer;
  sl: TStringList;
  p: PCounterRec;
  r: TCounterRec;
begin
  if not isMotohrEnabled then begin
    pnl.Height := 0;
    exit;
  end;

  self.pnl := pnl;
  Self.machName := machName;
  self.machdescr := machdescr;

  tagSystemTime := GetTagIndex(getMotohrModulePath + '.system.time');
  tagMachTime := GetTagIndex(getMotohrModulePath + '.' + machName + '.time');

  sl := TStringList.Create;
  smach := getMotohrModulePath + '.' + machName + '.cnt';
  FindTags(smach + '*', sl);
  for i:=0 to sl.Count-1 do begin

    tagname := sl[i];
    r.tagidx := Integer(sl.Objects[i]);
    r.sid := IStr(tagname, Length(smach) + 1);
    r.total := r.sid = COUNTER_TOTAL_SID;
    scnt := getMotohrModulePath + '.cnttype.' + r.sid + '.';
    r.descr := GetTagValueString(GetTagIndex(scnt + 'descr'));
    r.timer := GetTagValueByName(scnt + 'timer') > 0;

    if r.descr = '' then
      continue;

    if i >= counters.Count then begin
      p := new(PCounterRec);
      createLabels(pnl, p);
      counters.Add(p);
    end else begin
      p := counters[i];
    end;
    p.tagidx := r.tagidx;
    p.sid := r.sid;
    p.descr := r.descr;
    p.timer := r.timer;
    p.total := r.total;

    p.lbDescr.Caption := ' ' + getCounterTypeDescrShort(p.descr);
  end;

  i := sl.Count;
  while i < counters.Count do
    removeCounter(i);

  sl.Free;
  counters.Sort(@cmp);
  updateCounterTops;
  updateValues;
end;




procedure TMotohrPanel.updateCounterTops;
var
  i, h: Integer;
  p: PCounterRec;
begin
  h := 0;
  p := nil;
  for i:=0 to counters.Count-1 do begin
    p := PCounterRec(counters[i]);
    h := i * (p.lbDescr.Height + 4) + 8 + 20;
    p.lbDescr.Top := h;
    p.lbValue.Top := h;
    p.lbValue.Tag := i;

    p.lbDescr.Hint := iif(p.timer, 'Таймер', 'Счетчик') + ' моточасов - ' + getCounterTypeDescrLong(p.descr);
    p.lbValue.Hint := p.lbDescr.Hint;
  end;

  if p = nil then begin
    pnl.Height := 0;
  end else begin
    if folded then
      pnl.Height := 28
    else
      pnl.Height := h + p.lbDescr.Height + 13;
  end;
end;


procedure TMotohrPanel.removeCounter(index: integer);
begin
  freeLabels(PCounterRec(counters[index]));
  dispose(PCounterRec(counters[index]));
  counters.Delete(index);
end;


procedure TMotohrPanel.createLabels(pnl: TPanel; p: PCounterRec);
var
  lb: TLabel;

  procedure createLabel;
  begin
    lb := TLabel.Create(nil);
    lb.ShowHint := true;
    lb.Parent := pnl;
    lb.Transparent := False;
    lb.Font.Size := 10;
    lb.AutoSize := False;
    lb.Height := 20;
    lb.Layout := tlCenter;
    lb.Visible := true;
    lb.Cursor := crHandPoint;
  end;

begin
  createLabel;
  lb.Color := COLOR_NORMAL;
  lb.Width := 151;
  lb.Alignment := taLeftJustify;
  lb.Left := 14;
  p.lbDescr := lb;
  lb.OnClick := lbDescrClick;

  createLabel;
  lb.Font.Style := [fsBold];
  lb.Color := COLOR_NORMAL;
  lb.Width := 68;
  lb.Alignment := taRightJustify;
  lb.Left := pnl.Width - lb.Width - 14;
//  lb.Cursor := crHandPoint;
  lb.OnClick := labelClick;
  p.lbValue := lb;
end;


procedure TMotohrPanel.freeLabels(p: PCounterRec);
begin
  p.lbDescr.Free;
  p.lbValue.Free;
end;


procedure TMotohrPanel.updateValues;
var
  runsec: Int64;
  time: Int64;
  i: Integer;
  v: integer;
  d: Double;
  p: PCounterRec;
begin
  if not isMotohrEnabled then
    exit;

  if (tagMachTime < 0) or (tagSystemTime < 0) then
    Exit;

  runsec := 0;
  time := GetTagValueLong(tagMachTime);
  if time > 0 then
    runsec := GetTagValueLong(tagSystemTime) - time;

  for i:=0 to counters.Count-1 do begin
    p := PCounterRec(counters[i]);
    v := GetTagValue(p.tagidx);

    if v = COUNTER_DISABLED then begin
      p.lbValue.Caption := '';
      p.lbValue.Color := p.lbDescr.Color;
      p.sec := v;
    end else begin
      if runsec > 0 then begin
        if p.timer then
          v := v - runsec
        else
          v := v + runsec;
      end;
      p.sec := v;
      d := v / SEC_IN_HOUR;

      p.lbValue.Caption := Format('%.1f', [d]);
      if d < 0 then
        p.lbValue.Color := COLOR_NEGATIVE
      else
        p.lbValue.Color := COLOR_NORMAL;
    end;
  end;
end;


procedure TMotohrPanel.labelClick(Sender: TObject);
var
  res: Integer;
  p: PCounterRec;
  running: boolean;
  s: string;
  d: double;
  value: Integer;
  text, fio: string;
  descrLong: string;
begin
  p := counters[TLabel(Sender).tag];
  running := GetTagValueLong(tagMachTime) > 0;

  descrLong := getCounterTypeDescrLong(p.descr);
  value := 0;


  if p.total then begin
    if CurUserId <> USER_SUPERVISOR then
      Exit; 

    if running then begin
      showInfoDlg('Сбросить счетчик "Всего" можно только, если оборудование остановлено!');
      Exit;
    end else begin
      if showInfoDlg('Данное действие выполняется только при полной замене оборудования!' +
            #13#13'Сбросить счетчик "Всего"?', 'Внимание!', 'Сбросить', 'Отмена', '', clYellow) = 2 then
        Exit;
    end;
  end else

  if p.timer then begin
    res := showInfoDlg('Изменить таймер ' + descrLong + '?', 'Подтверждение', 'Установить', 'Отключить', 'Отмена');
    if res = 1 then begin
      s := '0';
      if ShowInputDialog(descrLong, 'Введите количество часов', s) then begin
        d := StrToFloatDef(s, 0.0);
        value := Trunc(d * SEC_IN_HOUR);
      end;
    end else

    if res = 2 then begin
      value := COUNTER_DISABLED;
    end else

      Exit;

  end else begin
    res := showInfoDlg('Изменить счетчик ' + descrLong + '?', 'Подтверждение', 'Сбросить', 'Отключить', 'Отмена');
    if res = 1 then begin
      //
    end else

    if res = 2 then begin
      value := COUNTER_DISABLED;
    end else

      exit;
  end;

  if p.sec = value then
    Exit;

  if not showMotohrMessage(text, fio) then
    exit;

  try
    startTransaction(true);
    insertLogbookRecord(now, p.descr, machName, text, fio, p.sec, value);
    SetTagValue(p.tagidx, value);
    commitTransaction;
  except
    on e : Exception do begin
      rollbackTransaction;
      showInfoDlg(e.Message, mtError, [mbOk], 0);
    end;
  end;
end;


procedure TMotohrPanel.lbDescrClick(Sender: TObject);
var
  w: TMotohrLogbookForm;
begin
  w := TMotohrLogbookForm.Create(form1);
  w.machName := machName;
  try
    w.ShowModal;
  finally
    w.free;
  end;
end;




procedure TMotohrPanel.toggleFolded;
begin
  folded := not folded;
  updateCounterTops;
end;

end.
