unit TagStorage;

interface
uses
  DataClientBase,
  rpTcpClient,
  PerlRegEx,
  Forms,
  Sysutils,
  Dialogs,
  Classes,
  Windows;


  procedure initDataClient;

  function GetTagCount: integer;
  function GetTagIndex(TagName: string): integer;
  function GetTagIndexWithLost(TagName: string; var LostTags: string): integer;
  function GetTagIndexFilter(TagName: string): integer;
  function GetTagName(idx: integer): string;
//  function GetTagExplotable(idx: integer): Boolean;
  function GetTagValueByName(TagName: string): integer;
  procedure SetTagValueByName(TagName: string; value: integer);
  function SetTagValueDlg(idx: integer; promt: string; var value: integer): boolean;

  function getTagType(idx: Integer): Integer;

  function GetTagValueBool(idx: integer): boolean;
  function GetTagValue(idx: integer): integer;
  function GetTagValueInt(idx: integer): integer;
  function GetTagValueLong(idx: integer): int64;
  function GetTagValueDouble(idx: integer): double;
  function GetTagValueString(idx: integer): string;
  function IsTagStatusGood(idx: integer): boolean;

  procedure SetTagValueBool(idx: integer; value: boolean);
  procedure SetTagValue(idx: integer; value: integer);
  procedure SetTagValueInt(idx: integer; value: integer);
  procedure SetTagValueLong(idx: integer; value: int64);
  procedure SetTagValueDouble(idx: integer; value: Double);
  procedure SetTagValueString(idx: integer; value: string);

  procedure FindTags(filter: string; list: TStringList);
  procedure FindTagsRegex(expr: string; list: TStringList);

  // old
  function SetAndSaveTagValueDlg(idx: integer; promt: string; var value: integer): boolean; //old   

var
  DataClient: TDataClient;


implementation
uses
  InputDialog,
  DataClientJrbustcp,
  DataClientRpsvrtcp,
  RpVisualMain,
  RpVisualGlobal,
  main,
  numbers,
  passwords,
  inifiles,
  status,
  connecting,
  rpTcpClientBase,
  TcpImportClient;



procedure initDataClient;
begin
  if (DataClient <> nil) and (DataClient.getProtocol <> DataClientProtocol) then begin
    DataClient.Free;
    DataClient := nil;
  end;

  if DataClient = nil then begin
    if DataClientProtocol = PROTOCOL_JRBUSTCP then
      DataClient := TDataClientJrbustcp.Create
    else
      DataClient := TDataClientRpsvrtcp.Create;
  end;

  DataClient.load(CurDir + RpVisualIniFile, 'RPVISUAL');
end;


function GetTagCount: integer;
begin
  result := DataClient.TagCount;
end;

function GetTagIndex(TagName: string): integer;
var
  k: integer;
begin
  k := -1;
  if DataClient.Connected then
    k := DataClient.GetTagIndex(TagName);

  result := k;
end;


function GetTagIndexWithLost(TagName: string; var LostTags: string): integer;
begin
  result := GetTagIndex(TagName);
  if result=-1 then
    LostTags := LostTags + TagName + #13#10;
end;


function GetTagIndexFilter(TagName: string): integer;
var
  i,k: integer;
begin
  k := -1;
  if DataClient.Connected then
    for i:=0 to DataClient.TagCount-1 do
      if CheckFilter(DataClient.getTagName(i), TagName) then begin
        k := i;
        break;
      end;
  result := k;
end;



//function GetTagExplotable(idx: integer): Boolean;
//begin
//  result := false;
//  if not DataClient.Connected then exit;
//  if (idx >= 0) and (idx < DataClient.TagCount) then
//    result := DataClient.getTagExplotable(idx)
//  else
//    result := false;
//end;


function GetTagValueByName(TagName: string): integer;
begin
  result := GetTagValue(GetTagIndex(TagName));
end;

procedure SetTagValueByName(TagName: string; value: integer);
begin
  SetTagValue(GetTagIndex(TagName), value);
end;


function GetTagName(idx: integer): string;
begin
  result := '';
  if not DataClient.Connected then exit;

  if (idx >= 0) and (idx < DataClient.TagCount) then
    result := DataClient.getTagName(idx);
end;




function SetTagValueDlgEx(idx: integer; promt: string; var value: integer; SaveFlag: boolean): boolean;
var
  s: string;
  v,i: integer;
  flag: boolean;
begin
  flag := False;
  result := false;

  s := IntToStr(GetTagValue(idx));

  if s='-1' then begin
    ShowMessage('Запись значения для этого параметра запрещена');
    exit;
  end;

  if ShowInputDialog('Настройка параметра', promt, s) then begin
    val(s, v, i);
    if i = 0 then begin
      value := v;
      SetTagValue(idx, {iif(SaveFlag, $10000, 0)} + v);
      flag := true;
    end;
  end;
  result := flag;
end;

function SetTagValueDlg(idx: integer; promt: string; var value: integer): boolean;
begin
  result := SetTagValueDlgEx(idx, promt, value, false);
end;

function SetAndSaveTagValueDlg(idx: integer; promt: string; var value: integer): boolean;
begin
  result := SetTagValueDlgEx(idx, promt, value, true);
end;

//////////////////// getters /////////////////////

function getTagType(idx: Integer): Integer;
begin
  if (not DataClient.Connected) or (idx < 0) or (idx >= DataClient.TagCount) then
    result := TAGTYPE_INT
  else
    result := DataClient.getTagType(idx);
end;

function GetTagValueBool(idx: integer): boolean;
begin
  if (not DataClient.Connected) or (idx < 0) or (idx >= DataClient.TagCount) then
    result := false
  else
    result := DataClient.getValBool(idx);
end;

function GetTagValue(idx: integer): integer;
begin
  result := 0;
  if not DataClient.Connected then exit;

  if (idx >= 0) and (idx < DataClient.TagCount) then begin
    if DataClient.getTagProp(idx) = tpIrregular then
      DataClient.setTagFlag(idx, tfInUse);

    result := DataClient.getValInt(idx);
  end else
    result := -1;
end;

function GetTagValueInt(idx: integer): integer;
begin
  if (not DataClient.Connected) or (idx < 0) or (idx >= DataClient.TagCount) then
    result := 0
  else
    result := DataClient.getValInt(idx);
end;

function GetTagValueLong(idx: integer): int64;
begin
  if (not DataClient.Connected) or (idx < 0) or (idx >= DataClient.TagCount) then
    result := 0
  else
    result := DataClient.getValLong(idx);
end;

function GetTagValueDouble(idx: integer): double;
begin
  if (not DataClient.Connected) or (idx < 0) or (idx >= DataClient.TagCount) then
    result := 0.0
  else
    result := DataClient.getValDouble(idx);
end;

function GetTagValueString(idx: integer): string;
begin
  if (not DataClient.Connected) or (idx < 0) or (idx >= DataClient.TagCount) then
    result := ''
  else
    result := DataClient.getValString(idx);
end;

function IsTagStatusGood(idx: integer): boolean;
begin
  if (not DataClient.Connected) or (idx < 0) or (idx >= DataClient.TagCount) then
    result := false
  else
    result := DataClient.isTagStatusGood(idx);
end;


//////////////////// setters /////////////////////

procedure SetTagValueBool(idx: integer; value: boolean);
begin
  if (not ReadOnlyMode) and (DataClient.Connected) and (idx >= 0) and (idx < DataClient.TagCount) then
    DataClient.setValBool(idx, value);
end;

procedure logSetTagValue(idx: Integer; valueNew: string);
begin
  _WritelnAdminLog('[SetTagValue] ' + DataClient.getTagName(idx) + ' = ' + DataClient.getValString(idx) + ' -> ' + valueNew);
end;

procedure SetTagValue(idx: integer; value: integer);
begin
  if (not ReadOnlyMode) and (DataClient.Connected) and (idx >= 0) and (idx < DataClient.TagCount) then begin

    if DataClient.getValInt(idx) <> value then
      logSetTagValue(idx, IntToStr(value));

    DataClient.setValInt(idx, value);
  end;
end;

procedure SetTagValueInt(idx: integer; value: integer);
begin
  if (not ReadOnlyMode) and (DataClient.Connected) and (idx >= 0) and (idx < DataClient.TagCount) then begin
    
    if DataClient.getValInt(idx) <> value then
      logSetTagValue(idx, IntToStr(value));

    DataClient.setValInt(idx, value);
  end;
end;

procedure SetTagValueLong(idx: integer; value: int64);
begin
  if (not ReadOnlyMode) and (DataClient.Connected) and (idx >= 0) and (idx < DataClient.TagCount) then begin
    
    if DataClient.getValLong(idx) <> value then
      logSetTagValue(idx, IntToStr(value));

    DataClient.setValLong(idx, value);
  end;
end;

procedure SetTagValueDouble(idx: integer; value: Double);
begin
  if (not ReadOnlyMode) and (DataClient.Connected) and (idx >= 0) and (idx < DataClient.TagCount) then begin

    if DataClient.getValDouble(idx) <> value then
      logSetTagValue(idx, FloatToStr(value));

    DataClient.setValDouble(idx, value);
  end;
end;

procedure SetTagValueString(idx: integer; value: string);
begin
  if (not ReadOnlyMode) and (DataClient.Connected) and (idx >= 0) and (idx < DataClient.TagCount) then begin

    if DataClient.getValString(idx) <> value then
      logSetTagValue(idx, value);

    DataClient.setValString(idx, value);
  end;
end;



procedure FindTags(filter: string; list: TStringList);
var
  i: Integer;
  s: string;
begin
  list.Clear;
  if not DataClient.Connected then
    exit;

  for i:=0 to DataClient.TagCount-1 do
  begin
    s := DataClient.getTagName(i);
    if CheckFilter(s, filter) then
      list.AddObject(s, TObject(i));
  end;
end;

procedure FindTagsRegex(expr: string; list: TStringList);
var
  i: Integer;
  s: string;
  r: TPerlRegEx;
begin
  list.Clear;
  if not DataClient.Connected then
    exit;

  r := TPerlRegEx.Create;
  r.RegEx := expr;
  for i:=0 to DataClient.TagCount-1 do
  begin
    s := DataClient.getTagName(i);
    r.Subject := s;
    if r.Match then
      list.AddObject(s, TObject(i));
  end;
end;



initialization
//  DataClient := nil;
//  initDataClient;

finalization
//  DataClient.Free

end.
