unit untAPI;

{$mode Delphi}{$H+}

interface

uses
  Classes, SysUtils, ISCJSON, ISCHttp, fgl;

const
  BASE_URL = 'https://sapi.moecube.com:444';
  API_ACC_SIGNIN = '/accounts/signin';
  API_ACC_AUTHUSER = '/accounts/authUser';
  PUZZLE_URL = 'http://rarnu.xyz:38383/api/mdpro3/puzzle/save';

type
  TCommonResult = class(TPersistent)
  private
    Fcode: Integer;
    Fmessage: string;
  published
    property code: Integer read Fcode write Fcode;
    property message: string read Fmessage write Fmessage;
  end;

type
  TMCUser = class(TPersistent)
  private
    Fid: Int64;
    Fusername: String;
    Fname: String;
    Femail: String;
    Favatar: String;
  published
    property id: Int64 read Fid write Fid;
    property username: string read Fusername write Fusername;
    property name: string read Fname write Fname;
    property email: String read Femail write Femail;
    property avatar: string read Favatar write Favatar;
  end;

  { MCUserWithToken }

  TMCUserWithToken = class(TPersistent)
  private
    Fuser: TMCUser;
    Ftoken: String;
  public
    constructor Create;
    destructor Destroy; override;
  published
    property user: TMCUser read Fuser;
    property token: String read Ftoken write Ftoken;
  end;

  { TMCSignInReq }

  TMCSignInReq = class(TPersistent)
  private
    Faccount: string;
    Fpassword: string;
  published
    property account: string read Faccount write Faccount;
    property password: string read Fpassword write Fpassword;
  end;

  { TEntityPuzzleAdd }

  TEntityPuzzle = class(TPersistent)
  private
    Fid: Int64;
    Fcontributor: string;
    FcoverCard: Int64;
    FluaScript: String;
    Fmessage: string;
    Fname: string;
    Fsolution: string;
    FuserId: Int64;
  published
    property id: Int64 read Fid write Fid;
    property name: string read Fname write Fname;
    property userId: Int64 read FuserId write FuserId;
    property contributor: string read Fcontributor write Fcontributor;
    property message: string read Fmessage write Fmessage;
    property solution: string read Fsolution write Fsolution;
    property coverCard: Int64 read FcoverCard write FcoverCard;
    property luaScript: String read FluaScript write FluaScript;
  end;

type
  
  { TAPI }


  TSavePuzzleResult = class(TCommonResult)
  private 
    Fdata: Int64;
  published
    property data: Int64 read Fdata write Fdata;
  end;

  TAPI = class
  public
    class function MCLogin(AAccount: String; APassword: String): TMCUserWithToken;
    class function MCValidate(AToken: String): TMCUser;
    // class function AddPuzzle(AP: TEntityPuzzle; AUserId: Int64; AToken: String): Boolean;
    // class function UpdatePuzzle(AP: TEntityPuzzle; AuserId: Int64; AToken: String): Boolean;
    class function SavePuzzle(AP: TEntityPuzzle; AUserId: Int64; AToken: String): TSavePuzzleResult;
  end;

implementation

{ MCUserWithToken }

constructor TMCUserWithToken.Create;
begin
  Fuser:= TMCUser.Create;
end;

destructor TMCUserWithToken.Destroy;
begin
  Fuser.Free;
  inherited Destroy;
end;

class function TAPI.MCLogin(AAccount: String; APassword: String): TMCUserWithToken;
var
  AUrl: String;
  AHeader: TFPGMap<String, String>;
  AData: TMCSignInReq;
  AJson: string;
  ARetJson: String;
  AUser: TMCUserWithToken;
begin
  AUrl := Format('%s%s', [BASE_URL, API_ACC_SIGNIN]);
  AHeader := TFPGMap<String, String>.Create;
  AHeader.Add('origin', 'https://accounts.moecube.com');
  AHeader.Add('referer', 'https://accounts.moecube.com');
  AHeader.Add('sec-fetch-dest', 'empty');
  AHeader.Add('sec-fetch-mode', 'cors');
  AHeader.Add('sec-fetch-site', 'same-site');
  AData:= TMCSignInReq.Create;
  AData.account := AAccount;
  AData.password := APassword;
  AJson := ISCObjectToJSONString<TMCSignInReq>(AData);
  ARetJson := ISCHttpPost(AUrl, AJson, AHeader);
  AData.Free;
  AHeader.Free;

  AUser := ISCJSONStringToObject<TMCUserWithToken>(ARetJson);
  if (AUser.token <> '') then begin
    Exit(AUser);
  end else begin
    AUser.Free;
    Exit(nil);
  end;;
end;

class function TAPI.MCValidate(AToken: String): TMCUser;
var
  AUrl: String;
  AHeader: TFPGMap<String, String>;
  ARetJson: string;
  AUser: TMCUser;
begin
  AUrl := Format('%s%s', [BASE_URL, API_ACC_AUTHUSER]);
  AHeader := TFPGMap<String, String>.Create;
  AHeader.Add('Authorization', Format('Bearer %s', [AToken]));
  ARetJson := ISCHttpGet(AUrl, AHeader);
  AHeader.Free;
  AUser := ISCJSONStringToObject<TMCUser>(ARetJson);
  if (AUser.id <> 0) then begin
    Exit(AUser);
  end else begin
    AUser.Free;
    Exit(nil);
  end;
end;

(*

class function TAPI.AddPuzzle(AP: TEntityPuzzle; AUserId: Int64; 
  AToken: String): Boolean;
var
  AUrl: String;
  AHeader: TFPGMap<String, String>;
  AReqJson: string;
  ARetJson: string;
  AResult: TCommonResult;
begin
  // add puzzle
  AUrl := PUZZLE_URL;
  AHeader := TFPGMap<String, String>.Create;
  AHeader.Add('ReqSource', 'MDPro3');
  AHeader.Add('userId', AUserId.ToString());
  AHeader.Add('token', AToken);
  AReqJson := ISCObjectToJSONString<TEntityPuzzle>(AP);
  ARetJson := ISCHttpPost(AUrl, AReqJson, AHeader);
  AHeader.Free;
  AResult := ISCJSONStringToObject<TCommonResult>(ARetJson);
  Result := AResult.message = 'true';
  AResult.Free;
end;

*)


(*

class function TAPI.UpdatePuzzle(AP: TEntityPuzzle; AuserId: Int64; 
  AToken: String): Boolean;
var
  AUrl: String;
  AHeader: TFPGMap<String, String>;
  AReqJson: string;
  ARetJson: string;
  AResult: TCommonResult;
begin
  // update puzzle
  AUrl := PUZZLE_URL;
  AHeader := TFPGMap<String, String>.Create;
  AHeader.Add('ReqSource', 'MDPro3');
  AHeader.Add('userId', AUserId.ToString());
  AHeader.Add('token', AToken);
  AReqJson := ISCObjectToJSONString<TEntityPuzzle>(AP);
  ARetJson := ISCHttpPut(AUrl, AReqJson, AHeader);
  AHeader.Free;
  AResult := ISCJSONStringToObject<TCommonResult>(ARetJson);
  Result := AResult.message = 'true';
  AResult.Free;
end;

*)

class function TAPI.SavePuzzle(AP: TEntityPuzzle; AUserId: Int64; AToken: String): TSavePuzzleResult;
var
  AUrl: String;
  AHeader: TFPGMap<String, String>;
  AReqJson: string;
  ARetJson: string;
  AResult: TSavePuzzleResult;
begin
  AUrl := PUZZLE_URL;
  AHeader := TFPGMap<String, String>.Create;
  AHeader.Add('ReqSource', 'MDPro3');
  AHeader.Add('userId', AUserId.ToString());
  AHeader.Add('token', AToken);
  AReqJson := ISCObjectToJSONString<TEntityPuzzle>(AP);
  ARetJson := ISCHttpPost(AUrl, AReqJson, AHeader);
  AHeader.Free;
  AResult := ISCJSONStringToObject<TSavePuzzleResult>(ARetJson);
  if (AResult.message = 'true') then begin
    Exit(AResult);
  end else begin
    AResult.Free;
    Exit(Nil);
  end;;
end;

end.

