unit fSettings;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants, uQ,
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
  ShellAPI, System.IOUtils, uDataBase,
  FMX.Controls.Presentation, FMX.Edit, uTWAuth, uRecords, uAPIDA, uShowText,
  json, uWSDA, fLog;

type
  TfrSettings = class(TFrame)
    GroupBox3: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label22: TLabel;
    edtBotName: TEdit;
    edtBotToken: TEdit;
    edtChannel: TEdit;
    btnGetToken: TButton;
    edtBotClientID: TEdit;
    btnGetClientID: TButton;
    btnOpenStream: TButton;
    btnGetTokenStreamer: TButton;
    edtBotTokenStreamer: TEdit;
    Label53: TLabel;
    GroupBox22: TGroupBox;
    btnDAGetCode: TButton;
    Label63: TLabel;
    edtDAClientID: TEdit;
    Label64: TLabel;
    edtDAClientSecret: TEdit;
    Label65: TLabel;
    edtDARedirectURL: TEdit;
    edtDACode: TEdit;
    Label66: TLabel;
    btnDAStart: TButton;
    btnGetDADef: TButton;
    cbDAAutoLogin: TCheckBox;
    cbTTVAutoLogin: TCheckBox;
    btnOpenRomaning: TButton;
    btnImportSettings: TButton;
    btnExportSettings: TButton;
    btnMaster: TButton;
    SaveDialog1: TSaveDialog;
    OpenDialog1: TOpenDialog;
    procedure btnGetTokenClick(Sender: TObject);
    procedure btnGetTokenStreamerClick(Sender: TObject);
    procedure btnOpenStreamClick(Sender: TObject);
    procedure btnDAGetCodeClick(Sender: TObject);
    procedure btnDAStartClick(Sender: TObject);
    procedure btnOpenRomaningClick(Sender: TObject);
    procedure btnImportSettingsClick(Sender: TObject);
    procedure btnExportSettingsClick(Sender: TObject);
    procedure btnMasterClick(Sender: TObject);
    procedure edtChannelExit(Sender: TObject);
  private
    { Private declarations }
    FAPIClient: TAPIClient;
    forbot: boolean;

    procedure OnTTWToken(txt: string);
    procedure OnTokenDA(txt: string);
    procedure HandleWSStatus(AStatusText: string; AStatusCode: integer);
    procedure HandleWSDonate(aNick, aMessage, aSum: string);
  public
    { Public declarations }
    FWSClient: TWSClient;
    destructor Destroy; override;
    procedure init();

  end;

implementation

{$R *.fmx}

uses uGeneral;

procedure TfrSettings.btnDAGetCodeClick(Sender: TObject);
var
  twa: TTTWAuth;
  Url: string;
begin
  if (edtDAClientSecret.text = '') or (edtDAClientID.text = '') or
    (edtDARedirectURL.text = '') then
    exit;

  Url := 'https://www.donationalerts.com/oauth/authorize?client_id=' +
    edtDAClientID.text +
    '&redirect_uri=http://localhost/da&response_type=code&scope=oauth-user-show+oauth-donation-subscribe';
  twa := TTTWAuth.Create;
  twa.OnToken := OnTokenDA;
  twa.StartServer(Url);
  // ttw_Auth будет освобожден автоматически после получения токена (см. uTWAuth)
end;

procedure TfrSettings.OnTokenDA(txt: string);
begin
  edtDACode.text := txt;
  if cbDAAutoLogin.IsChecked then
  begin
    btnDAStartClick(self);
  end;
end;


procedure TfrSettings.btnDAStartClick(Sender: TObject);
var
  UserInfo: TJSONObject;
  Data: TJSONObject;
begin
  if btnDAStart.text = 'Подключиться' then
  begin
    UserInfo := nil;
    try
      try
        if not Assigned(FAPIClient) then
          init;

        if FAPIClient.Token = '' then
        begin
          try
            FAPIClient.Token := FAPIClient.GetAccessToken(
              edtDAClientID.text,
              edtDAClientSecret.text,
              edtDARedirectURL.text,
              edtDACode.text
            );
          except
            on E: Exception do
            begin
              TTW_Bot.toLog('fSettings', 'btnDAStartClick', 'Ошибка получения токена: ' + E.Message,2);
              Exit;
            end;
          end;

          FWSClient.APIClient := FAPIClient;

          try
            UserInfo := FAPIClient.GetUserInfo;
            Data := UserInfo.GetValue<TJSONObject>('data');
            FWSClient.Wsstoken := Data.GetValue<string>('socket_connection_token');
            FWSClient.WSID := Data.GetValue<string>('id');
          except
            on E: Exception do
            begin
              TTW_Bot.toLog( 'fSettings','btnDAStartClick', 'Ошибка получения UserInfo: ' + E.Message,2);
              Exit;
            end;
          end;
        end;

        try
          FWSClient.Connect('wss://centrifugo.donationalerts.com/connection/websocket');
          FWSClient.Send(Format(
            '{"params":{"token":"%s"},"id":1}',
            [FWSClient.Wsstoken]
          ));
        except
          on E: Exception do
            TTW_Bot.toLog( 'fSettings','btnDAStartClick', 'Ошибка подключения к WebSocket: ' + E.Message,2);
        end;

      except
        on E: Exception do
          TTW_Bot.toLog('fSettings', 'btnDAStartClick', 'Неизвестная ошибка: ' + E.Message,2);
      end;
    finally
      UserInfo.Free;
    end;
  end
  else
  begin
    try
    edtDACode.Text:='';
      if Assigned(FWSClient) then
      begin
        try
          FWSClient.Disconnect;
        except
          on E: Exception do
            TTW_Bot.toLog( 'fSettings', 'btnDAStartClick', 'Ошибка при отключении WS: ' + E.Message,2);
        end;
        FreeAndNil(FWSClient);
      end;

      FreeAndNil(FAPIClient);
    finally
      btnDAStart.ImageIndex := 18;
      btnDAStart.text := 'Подключиться';
    end;
  end;
end;

procedure TfrSettings.btnExportSettingsClick(Sender: TObject);
var
  DestinationFile: string;
begin
  SaveDialog1.FileName := TPath.GetFileName(myConst.DBPath);
  if SaveDialog1.Execute then
  begin
    DestinationFile := SaveDialog1.FileName;
    TFile.Copy(myConst.DBPath, DestinationFile, True);
  end;
end;

procedure TfrSettings.btnGetTokenClick(Sender: TObject);
var
  s: string;
  sope: string;
  ttw_Auth: TTTWAuth;
begin
  ttw_Auth := TTTWAuth.Create;
  ttw_Auth.OnToken := OnTTWToken;
  // ttw_Auth будет освобожден автоматически после получения токена (см. uTWAuth)
  sope := 'moderator:manage:shoutouts' + '+moderator:manage:announcements' +
    '+moderator:manage:banned_users' + '+moderator:manage:warnings' +
    '+moderator:read:followers' + '+channel:manage:raids' +
    '+channel:manage:moderators' + '+channel:read:redemptions' + '+chat:read' +
    '+chat:edit+user:read:emotes';
  sope := StringReplace(sope, ':', '%3A', [rfReplaceAll]);

  s := 'https://id.twitch.tv/oauth2/authorize?client_id=' + edtBotClientID.text
    + '&redirect_uri=http://localhost&response_type=token&' + 'scope=' + sope;
  ttw_Auth.StartServer('');
  forbot := True;
  fShowText.Memo1.Lines.text := s;
  fShowText.Show;
  fShowText.Memo1.WordWrap := True;

end;

procedure TfrSettings.btnGetTokenStreamerClick(Sender: TObject);
var
  sope: string;
  ttw_Auth: TTTWAuth;
begin
  ttw_Auth := TTTWAuth.Create;
  ttw_Auth.OnToken := OnTTWToken;
  sope := 'channel:read:redemptions' + '+channel:manage:vips' +
    '+moderator:read:followers' + '+channel:read:subscriptions' +
    '+channel:manage:moderators' + '+channel:manage:redemptions';
  sope := StringReplace(sope, ':', '%3A', [rfReplaceAll]);
  ttw_Auth.StartServer('https://id.twitch.tv/oauth2/authorize?client_id=' +
    edtBotClientID.text + '&redirect_uri=http://localhost&response_type=token&'
    + 'scope=' + sope);
  forbot := false;
end;

procedure TfrSettings.btnImportSettingsClick(Sender: TObject);
var
  SourceFile, DestinationDir, DestinationFile: string;
begin
  if OpenDialog1.Execute then
  begin
    DB.Free;
    SourceFile := OpenDialog1.FileName;
    DestinationDir := myConst.DBPath;
    DestinationFile := myConst.DBPath;
    TFile.Copy(SourceFile, DestinationFile, True);
    DB := TSettingsDatabase.Create(myConst.DBPath);
  end;
end;

procedure TfrSettings.btnMasterClick(Sender: TObject);
var
  qf: tfrmq;

begin
  qf := tfrmq.Create(nil);
  try
    qf.SetLabelText('Введите ник аккаунта от которого будет писать бот:');
    if qf.ShowModal = mrOk then
      edtBotName.text := qf.GetEditText;
    qf.SetLabelText('Введите ник стримера где будет работать бот:');
    if qf.ShowModal = mrOk then
      edtChannel.text := qf.GetEditText;
    if btnGetClientID.Visible then
    begin
      edtBotClientID.text := appconst.TTV_ClientID;
      showmessage('Появится окно, там будет ссылка. ' + #13 +
        'Скопируй ее и открой в браузере где авторизован бот.  ' + #13 +
        'Если понял - жми ОК');
      btnGetTokenClick(self);
      showmessage
        ('Когда ссылка пропадет жми "Получить Token" около поля "API Token Стримера". '
        + #13 + 'Если понял - жми ОК');
    end
    else
    begin
      showmessage('Нет файла ключей! ' + #13 +
        'Введите ClientID вручную и продолжите настройку без мастера!');
    end;

  finally
    qf.Free;
  end;
end;

procedure TfrSettings.btnOpenRomaningClick(Sender: TObject);
begin
  ShellExecute(0, 'open', pwidechar(ExtractFilePath(myConst.DBPath)),
    nil, nil, 1);
end;

procedure TfrSettings.btnOpenStreamClick(Sender: TObject);
begin
  ShellExecute(0, 'open', pwidechar('https://www.twitch.tv/' + edtChannel.text),
    nil, nil, 1);
end;

destructor TfrSettings.Destroy;
begin
if Assigned(FWSClient) then
  begin
    try
      FWSClient.Disconnect; // если есть метод отключения
    except end;
    FreeAndNil(FWSClient);
  end;
  FreeAndNil(FAPIClient);
  inherited;
end;

procedure TfrSettings.edtChannelExit(Sender: TObject);
begin
  if Sender is TEdit then
    DB.WriteSetting(TEdit(Sender).Name, TEdit(Sender).text);
  if Sender is TCheckBox then
    if TCheckBox(Sender).IsChecked then
      DB.WriteSetting(TCheckBox(Sender).Name, 'True')
    else
      DB.WriteSetting(TCheckBox(Sender).Name, 'False');
end;

procedure TfrSettings.init;
begin
if not Assigned(FAPIClient) then
    FAPIClient := TAPIClient.Create;
  if not Assigned(FWSClient) then
  begin
    FWSClient := TWSClient.Create;
    FWSClient.OnStatus := HandleWSStatus;
    FWSClient.OnDonate := HandleWSDonate;
    FWSClient.OnLog := TTW_Bot.toLog;
  end;
end;

procedure TfrSettings.OnTTWToken(txt: string);
begin
  fShowText.Close;
  if forbot then
  begin
    edtBotToken.text := txt;
    DB.WriteSetting('edtBotToken', txt);
  end
  else
  begin
    edtBotTokenStreamer.text := txt;
    DB.WriteSetting('edtBotTokenStreamer', txt);
  end;

end;

procedure TfrSettings.HandleWSDonate(aNick, aMessage, aSum: string);
begin
  // fDonats.OnDADonate(aNick, aMessage, aSum);
  TTW_Bot.frOBS1.toEventWebServer(aNick,aSum,aMessage);
  TTW_Bot.frEvents1.OnDonate(aNick, aMessage, aSum);

end;

procedure TfrSettings.HandleWSStatus(AStatusText: string; AStatusCode: integer);
begin
   TTW_Bot.tolog('fSettings','HandleWSStatus',AStatusText,3);
  TTW_Bot.Label8.text := AStatusText;
  case AStatusCode of
    0:
      begin
        btnDAStart.ImageIndex := 1;
        btnDAStart.text := 'Отключиться';
      end;
  else
    begin
      btnDAStart.ImageIndex := 18;
      btnDAStart.text := 'Подключиться';
    end;
  end;

end;

end.
