unit XData.Utils;

{$I XData.inc}

interface

uses
  SysUtils;

type
  TXDataUtils = class
  public
    class function GetNameAndKey(const Input: string; out Name, Key: string): boolean;
    class procedure GetQualifiedName(const AQualifiedName: string; out APrefix, AName: string); {$IFNDEF PAS2JS}{$IFNDEF PAS2JS}static;{$ENDIF}{$ENDIF}
    class function XSBoolean(const S: string; ADefault: boolean = false): boolean; {$IFNDEF PAS2JS}inline; static;{$ENDIF}
//    class function DateTimeToDayTimeDuration(const Value: TTime): string; {$IFNDEF PAS2JS}static;{$ENDIF}
//    class function TryDayTimeDurationToDateTime(const Value: string; out Time: TTime): boolean; {$IFNDEF PAS2JS}static;{$ENDIF}
    class function CombineUrlFast(const AbsoluteUrl, RelativeUrl: string): string; {$IFNDEF PAS2JS}static;{$ENDIF}
    {$IFDEF PAS2JS}
    class function DateTimeToUnix(const Value: TDateTime): Integer;
    {$ELSE}
    class function DateTimeToUnix(const Value: TDateTime): Int64; static;
    {$ENDIF}
    class function DateTimeToJson(const Value: TDateTime): string; {$IFNDEF PAS2JS}static;{$ENDIF}
  end;

implementation

{ TXDataUtils }

class function TXDataUtils.CombineUrlFast(const AbsoluteUrl,
  RelativeUrl: string): string;
begin
  // Do a faster url combination because we know RelativeUrl comes correct
  Result := AbsoluteUrl;
  if (Length(Result) > 0) and (Result[Length(Result)] <> '/') then
    Result := Result + '/';
  Result := Result + RelativeUrl;
end;

//class function TXDataUtils.DateTimeToDayTimeDuration(
//  const Value: TTime): string;
//var
//  D, H, M, S, MS: Word;
//begin
//  D := Trunc(Value);
//  DecodeTime(Value, H, M, S, MS);
//  Result := 'P';
//  if D > 0 then
//    Result := Result + IntToStr(D) + 'D';
//  if H > 0 then
//    Result := Result + IntToStr(H) + 'H';
//  if M > 0 then
//    Result := Result + IntToStr(M) + 'M';
//  if S > 0 then
//    Result := Result + IntToStr(S) + 'S';
//  if Result = 'P' then
//    Result := 'P0D';
//end;

class function TXDataUtils.DateTimeToJson(const Value: TDateTime): string;
begin
  Result := Format('\/Date(%d)\/', [DateTimeToUnix(Value) * 1000]);
end;

{$IFDEF PAS2JS}
class function TXDataUtils.DateTimeToUnix(const Value: TDateTime): Integer;
{$ELSE}
class function TXDataUtils.DateTimeToUnix(const Value: TDateTime): Int64;
{$ENDIF}
begin
  Result := Round((Value - UnixDateDelta) * SecsPerDay);
end;

class function TXDataUtils.GetNameAndKey(const Input: string; out Name, Key: string): boolean;
var
  P1: integer;
  Len: integer;
  KeyLen: integer;
begin
  P1 := Pos('(', Input);
  Len := Length(Input);
  KeyLen := Len - P1 - 1;
  Result :=
    (P1 > 1) //open parentesis must exist and must have one space for name
    and (Len >= 4) // at least one char for name and one char for key plus 2 parentesis: A(B)
    and (Input[Len] = ')') // last char must be close parentesis
    and (KeyLen > 0); // and key must have at least one char
  if Result then
  begin
    Name := Copy(Input, 1, P1 - 1);
    Key := Copy(Input, P1 + 1, KeyLen);
  end;
end;

class procedure TXDataUtils.GetQualifiedName(const AQualifiedName: string;
  out APrefix, AName: string);
var
  I, Len: integer;
begin
  Len := Length(AQualifiedName);
  I := Len;
  while I > 0 do
  begin
    if AQualifiedName[I] = '.' then
      break;
    Dec(I);
  end;
  if I > 0 then
  begin
    APrefix := Copy(AQualifiedName, 1, I - 1);
    AName := Copy(AQualifiedName, I + 1, MaxInt)
  end
  else
  begin
    APrefix := '';
    AName := AQualifiedName;
  end;
end;

//class function TXDataUtils.TryDayTimeDurationToDateTime(const Value: string;
//  out Time: TTime): boolean;
//var
//  Len: integer;
//  Day, Hour, Min, Sec: integer;
//
//  function ExtractNumber(const Value: string; var I: integer): boolean;
//  var
//    Start: integer;
//    C: Char;
//    Number: integer;
//  begin
//    Start := I;
//    {$IFDEF DELPHIXE4_LVL}
//    while (I <= Len) and Value[I].IsDigit do
//    {$ELSE}
//    while (I <= Len) and IsDigit(Value[I]) do
//    {$ENDIF}
//      Inc(I);
//    Result := TryStrToInt(Copy(Value, Start, I - Start), Number) and (I <= Len);
//    if Result then
//    begin
//      C := Value[I];
//      Inc(I);
//      if C = 'D' then
//        Day := Number
//      else
//      if C = 'H' then
//        Hour := Number
//      else
//      if C = 'M' then
//        Min := Number
//      else
//      if C = 'S' then
//        Sec := Number
//      else
//        Result := false;
//    end;
//  end;
//
//var
//  I: integer;
//begin
//  Len := Length(Value);
//  if (Len = 0) or (Value[1] <> 'P') then
//    Exit(false);
//  I := 2;
//
//  Day := 0;
//  Hour := 0;
//  Min := 0;
//  Sec := 0;
//
//  // at least one part must exist
//  if not ExtractNumber(Value, I) then
//    Exit(false);
//
//  // now extract as many as exist
//  while ExtractNumber(Value, I) do ;
//  Time := EncodeTime(Hour, Min, Sec, 0);
//  Result := true;
//end;

class function TXDataUtils.XSBoolean(const S: string; ADefault: boolean): boolean;
begin
  if S = '' then
    Exit(ADefault);
  Result := (S = 'true') or (S = '1') or (S = 'yes');
end;

end.

