unit VisSeqcApi;

interface
uses
  pFIBDatabase, pFIBDataSet, Classes, StdCtrls, SysUtils, Dialogs;

type
  TSeqcConnection = class
  public

    // Creates instanes of the class and instantly connects to a database
    // It also initializes all internal stuff for further database interaction
    constructor create(dbNameParam: string); virtual; abstract;

    // Fills an object of the TStrings class with
    // routes NAMEs and their CODEs from the ROOTS table. Use Objects[] property to reach CODE.
    // In addition you can use a filter with standard wildcards to skip unwanted routes names.
    procedure getRootList(filter: string; list: TStrings); virtual; abstract;

    // Fills a given combobox with rout NAMEs and their CODEs from the ROOTS table.
    // After getting data from database, tries to locate current
    procedure getRootListCombobox(cmb: TComboBox; filter: string; TagPath, TagRoot: string); virtual; abstract;


    //
    //
    function installRoot(code: integer; TagPath, TagRoot: string): boolean; virtual; abstract;


    //
    // Returns reference to the internal dataset
    function getDataset: TpFIBDataSet; virtual; abstract;
    
    function isConnected: boolean; virtual; abstract;
  end;




  TSeqcRootData = class
  public
    //
    // Constructs instance, reads detail route (of a given code) data from db and prepares tag indexes
    constructor create(conn: TSeqcConnection; code: Integer; TagPath, TagRoot: string); virtual; abstract;

    //
    // Returns number of devices in the route
    function getDeviceCount: Integer; virtual; abstract;

    //
    // Represents internal data in text format
    function toString: string; virtual; abstract;

    //
    // Installs the root to a PLC
    function installRootToPLC(timeout: Integer): boolean; virtual; abstract;
  end;

////////////////////////////////////////////////////////////////////////////////
// Helper procs
////////////////////////////////////////////////////////////////////////////////

  //
  // Saves in RpVisual.ini current code of a given combobox
  // Example of ini-content:
  //   [Seqc]
  //   SHEL2_SC01=123
  procedure iniSaveRootCodeCombobox(cmb: TComboBox; TagPath, TagRoot: string);


  //
  // Determines whether device is being used
  // Return code:
  //  =0 device isn't used by none of seqc
  //  =1 device is used without soleowner flag
  //  =2 device is used with soleowner flag
  function getDeviceUsageInfo(addr: integer; seqcTagFilter: string): integer;

implementation
uses
  RpVisualGlobal,
  Numbers,
  TagStorage,
  IniFiles;




procedure iniSaveRootCodeCombobox(cmb: TComboBox;
  TagPath, TagRoot: string);
var
  code: integer;
  i: Integer;
begin
  i := cmb.ItemIndex;
  if i=-1 then Exit;

  code := Integer(cmb.Items.Objects[i]);

  with TIniFile.Create(CurDir + RpVisualIniFile) do try
    WriteInteger('Seqc', TagPath+'_'+TagRoot, code);
  finally
    Free;
  end;

end;

function getDeviceUsageInfo(addr: integer; seqcTagFilter: string): integer;
var
  v,k,i,j,n, idx: Integer;
  s,s1,s2,flt1,tagname: string;
  useFilter: Boolean;
begin
  result := 0;
//  sole := False;

  useFilter := seqcTagFilter <> '';
  flt1 := '*.SEQC_*_Sost';

  n := GetTagCount;
  for i:=0 to n-1 do begin
    // search for running seqc
    s := GetTagName(i);
    if not CheckFilter(s, flt1) then Continue;
    if useFilter then
      if not CheckFilter(s, seqcTagFilter) then Continue;

    if GetTagValue(i) = 0 then Continue;

    // pick up its tagname
//    k := Pos('.SEQC_', s)+6;
    tagname := Copy(s, 1, Length(s)-4);


    // search for index of addr in addresses
    idx:=-1;
    j:=0;
    s1 := tagname + 'Address';
    repeat
      s2 := s1 + IntToStr(j);
      k := GetTagIndex(s2);
      if k<0 then
        Break
      else begin
        v := GetTagValue(k);
        if v = addr then begin
          idx:=j;
          Break;
        end;
        if v = $FFFF then
          Break;
      end;
      Inc(j);
    until false;


    // check if addr in soleowner mode
    if idx>=0 then begin
      result := 1;
      k := GetTagIndex(tagname + 'ModeFlags' + inttostr(idx));
      if k>=0 then
        if (GetTagValue(k) and $40) > 0 then begin
          result := 2;
          Break;
        end;
    end;
  end;
end;

end.
