unit untUtils;

interface

uses
  Classes, SysUtils, untCard, StrUtils;

function ElementNameToFieldRec(AName: string): TFieldRec;
function ElementNameToFieldStrings(fr: TFieldRec): TFieldStrings;

function CardTypeToReadable(ct: TCardType): string;

function PickOneCardFromList(list: TArray<ICard>; ACardId: Int64; AOwner: TCardOwner; APlayer: TCardPlayer; ALocation: TCardLocation; ASeq: Integer): ICard;
function WorkAsToCodeName(cwa: TCardWorkAs): String;

function GetFirstCardFromScriptCode(ACode: string): Int64;

type
  EXT = class
  public
    class function IfThen<T>(ACondition: Boolean; ATrue: T; AFalse: T): T;
  end;

  TCardUtil = class
  public
    class function ParseCardType(typ: Int64): TCardType;
    class function IsXyzMonster(typ: Int64): Boolean;
    class function IsLinkMonster(typ: Int64): Boolean;
  end;

implementation

uses
  untArrayHelper, untConstant;

class function EXT.IfThen<T>(ACondition: Boolean; ATrue: T; AFalse: T): T;
begin
  if ACondition then begin
    Exit(ATrue);
  end else begin
    Exit(AFalse);
  end;
end;

function ElementNameToFieldRec(AName: string): TFieldRec;
var
  rec: TFieldRec;
  n: string;
  seq: Integer;
  lo: string;
begin
  n := RightStr(AName, AName.Length - 3);
  if (n.StartsWith('M')) then begin
    rec.Owner:= foShare;
    rec.Location:= clMZone;
    seq := StrToInt(RightStr(n, 1));
    rec.Seq:= seq;
  end else begin
    if (n.StartsWith('P0')) then begin
      rec.Owner:= foSelf;
    end else if (n.StartsWith('P1')) then begin
      rec.Owner:= foOpponent;
    end;
    n := RightStr(n, n.Length - 2);
    lo := LeftStr(n, 1);
    if (lo = 'M') then begin  // monster
      rec.Location:= clMZone;
      seq := StrToInt(RightStr(n, 1));
      rec.Seq:= seq;
    end else if (lo = 'S') then begin // spell
      rec.Location:= clSZone;
      seq := StrToInt(RightStr(n, 1));
      rec.Seq:= seq;
    end else if (lo = 'D') then begin // deck
      rec.Location:= clDeck;
      rec.Seq:= 0;
    end else if (lo = 'G') then begin // grave
      rec.Location:= clGrave;
      rec.Seq:= 0;
    end else if (lo = 'E') then begin // extra
      rec.Location:= clExtra;
      rec.Seq:= 0;
    end else if (lo = 'R') then begin // removed
      rec.Location:= clRemoved;
      rec.Seq:= 0;
    end else if (lo = 'H') then begin // hand
      rec.Location:= clHand;
      rec.Seq:= 0;
    end;
  end;

  Exit(rec);
end;

function ElementNameToFieldStrings(fr: TFieldRec): TFieldStrings;
var
  rec: TFieldStrings;
begin
  case fr.Owner of
  foSelf:
    begin
      rec.Owner:= OWNER_SELF;
      rec.Color:= COLOR_SELF;
    end;
  foOpponent:
    begin
      rec.Owner:= OWNER_OPPONENT;
      rec.Color:= COLOR_OPPONENT;
    end;
  foShare:
    begin
      rec.Owner:= OWNER_SHARE;
      rec.Color:= COLOR_SHARE;
    end;
  end;
  case fr.Location of
    clMZone:
      if (fr.Seq >= 5) then begin
        rec.Location:= Format(LOC_EXTRA_MONSTER, [fr.Seq]);
      end else begin
        rec.Location:= Format(LOC_MZONE, [fr.Seq]);
      end;
    clSZone:
      if (fr.Seq = 0) or (fr.Seq = 4) then begin
        rec.Location:= Format(LOC_SZONE2, [fr.seq]);
      end else if (fr.Seq = 5) then begin
        rec.Location:= Format(LOC_FIELD_MAGIC, [fr.Seq]);
      end else begin
        rec.Location:= Format(LOC_SZONE, [fr.seq]);
      end;
    clDeck: rec.Location:= LOC_DECK;
    clGrave: rec.Location:= LOC_GRAVE;
    clExtra: rec.Location:= LOC_EXTRA;
    clRemoved: rec.Location:= LOC_REMOVED;
    clHand: rec.Location:= LOC_HAND;
  end;

  Exit(rec);
end;

function CardTypeToReadable(ct: TCardType): string;
begin
  case ct of
  ctMonster: Exit('怪兽');
  ctSpell: Exit('魔法');
  ctTrap: Exit('陷阱');
  ctPendulum: Exit('灵摆');
  end;
end;

function PickOneCardFromList(list: TArray<ICard>; ACardId: Int64; AOwner: TCardOwner; APlayer: TCardPlayer; ALocation: TCardLocation; ASeq: Integer): ICard;
var
  c: ICard;
  i: Integer;
begin
  for i := 0 to list.Count - 1 do begin
    c := list[i];
    if (c.GetCardId = ACardId) and (c.GetOwner = AOwner) and (c.GetPlayer = APlayer) and (c.GetLocation = ALocation) and (c.GetSeq = ASeq) then begin
      Exit(c);
    end;
  end;
  Exit(nil);
end;

function WorkAsToCodeName(cwa: TCardWorkAs): String;
begin
  case cwa of
  waNormalMonster: Exit('TYPE_MONSTER+TYPE_NORMAL');
  waEffectMonster: Exit('TYPE_MONSTER+TYPE_EFFECT');
  waRitualMonster: Exit('TYPE_MONSTER+TYPE_RITUAL');
  waFusionMonster: Exit('TYPE_MONSTER+TYPE_FUSION');
  waSynchroMonster: Exit('TYPE_MONSTER+TYPE_SYNCHRO');
  waXyzMonster: Exit('TYPE_MONSTER+TYPE_XYZ');
  waLinkMonster: Exit('TYPE_MONSTER+TYPE_LINK');
  waPendulumMonster: Exit('TYPE_MONSTER+TYPE_PENDULUM');
  waToken: Exit('TYPE_MONSTER+TYPE_TOKEN');
  waNormalSpell: Exit('TYPE_SPELL+TYPE_NORMAL');
  waEquipSpell: Exit('TYPE_SPELL+TYPE_EQUIP');
  waFieldSpell: Exit('TYPE_SPELL+TYPE_FIELD');
  waQuickPlaySpell: Exit('TYPE_SPELL+TYPE_QUICKPLAY');
  waContinousSpell: Exit('TYPE_SPELL+TYPE_CONTINUOUS');
  waRitualSpell: Exit('TYPE_SPELL+TYPE_RITUAL');
  waNormalTrap: Exit('TYPE_TRAP+TYPE_NORMAL');
  waContinousTrap: Exit('TYPE_TRAP+TYPE_CONTINUOUS');
  waCounterTrap: Exit('TYPE_TRAP+TYPE_COUNTER');
  end;
  Exit('');
end;

function GetFirstCardFromScriptCode(ACode: string): Int64;
var
  i: Integer;
  tmp: string;
begin
  // GetFirstCardFromScriptCode
  with TStringList.Create do begin
    Text:= ACode;
    for i := 0 to Count - 1 do begin
      if (Strings[i].Contains('Debug.AddCard(')) then begin
        tmp := Strings[i];
        tmp := tmp.Substring(tmp.IndexOf('(') + 1);
        tmp := tmp.Substring(0, tmp.IndexOf(','));
        Break;
      end;
    end;
    Free;
  end;
  Exit(StrToInt64Def(tmp, 0));
end;

{ TCardUtil }

class function TCardUtil.IsLinkMonster(typ: Int64): Boolean;
var
  AType: TCardType;
begin
  AType:= ParseCardType(typ);
  if (AType = ctMonster) then begin
    Exit(typ and $4000000 <> 0);
  end else begin
    Exit(False);
  end;

end;

class function TCardUtil.IsXyzMonster(typ: Int64): Boolean;
var
  AType: TCardType;
begin
  AType:= ParseCardType(typ);
  if (AType = ctMonster) or (AType = ctPendulum) then begin
    Exit(typ and $800000 <> 0);
  end else begin
    Exit(False);
  end;

end;

class function TCardUtil.ParseCardType(typ: Int64): TCardType;
begin
  if (typ and $1000000 <> 0) then begin
    Exit(ctPendulum);
  end else if (typ and $4 <> 0) then begin
    Exit(ctTrap);
  end else if (typ and $2 <> 0) then begin
    Exit(ctSpell);
  end else begin
    Exit(ctMonster);
  end;
end;

end.
