package auth

import (
	

	

	
	
)

// ErrPasswordInvalid means that password provided to Password is invalid.
//
// Note that telegram does not trim whitespace characters by default, check
// that provided password is expected and clean whitespaces if needed.
// You can use strings.TrimSpace(password) for this.
var ErrPasswordInvalid = errors.New("invalid password")

// Password performs login via secure remote password (aka 2FA).
//
// Method can be called after SignIn to provide password if requested.
func ( *Client) ( context.Context,  string) (*tg.AuthAuthorization, error) {
	,  := .api.AccountGetPassword()
	if  != nil {
		return nil, errors.Wrap(, "get SRP parameters")
	}

	,  := PasswordHash([]byte(), .SRPID, .SRPB, .SecureRandom, .CurrentAlgo)
	if  != nil {
		return nil, errors.Wrap(, "compute password hash")
	}

	,  := .api.AuthCheckPassword(, &tg.InputCheckPasswordSRP{
		SRPID: .SRPID,
		A:     .A,
		M1:    .M1,
	})
	if tg.IsPasswordHashInvalid() {
		return nil, ErrPasswordInvalid
	}
	if  != nil {
		return nil, errors.Wrap(, "check password")
	}
	,  := checkResult()
	if  != nil {
		return nil, errors.Wrap(, "check")
	}
	return , nil
}

// SendCodeOptions defines how to send auth code to user.
type SendCodeOptions struct {
	// AllowFlashCall allows phone verification via phone calls.
	AllowFlashCall bool
	// Pass true if the phone number is used on the current device.
	// Ignored if AllowFlashCall is not set.
	CurrentNumber bool
	// If a token that will be included in eventually sent SMSs is required:
	// required in newer versions of android, to use the android SMS receiver APIs.
	AllowAppHash bool
}

// SendCode requests code for provided phone number, returning code hash
// and error if any. Use AuthFlow to reduce boilerplate.
//
// This method should be called first in user authentication flow.
func ( *Client) ( context.Context,  string,  SendCodeOptions) (tg.AuthSentCodeClass, error) {
	var  tg.CodeSettings
	if .AllowAppHash {
		.SetAllowAppHash(true)
	}
	if .AllowFlashCall {
		.SetAllowFlashcall(true)
	}
	if .CurrentNumber {
		.SetCurrentNumber(true)
	}

	,  := .api.AuthSendCode(, &tg.AuthSendCodeRequest{
		PhoneNumber: ,
		APIID:       .appID,
		APIHash:     .appHash,
		Settings:    ,
	})
	if  != nil {
		return nil, errors.Wrap(, "send code")
	}
	return , nil
}

// ErrPasswordAuthNeeded means that 2FA auth is required.
//
// Call Client.Password to provide 2FA password.
var ErrPasswordAuthNeeded = errors.New("2FA required")

// SignIn performs sign in with provided user phone, code and code hash.
//
// If ErrPasswordAuthNeeded is returned, call Password to provide 2FA
// password.
//
// To obtain codeHash, use SendCode.
func ( *Client) ( context.Context, , ,  string) (*tg.AuthAuthorization, error) {
	,  := .api.AuthSignIn(, &tg.AuthSignInRequest{
		PhoneNumber:   ,
		PhoneCodeHash: ,
		PhoneCode:     ,
	})
	if tgerr.Is(, "SESSION_PASSWORD_NEEDED") {
		return nil, ErrPasswordAuthNeeded
	}
	if  != nil {
		return nil, errors.Wrap(, "sign in")
	}
	,  := checkResult()
	if  != nil {
		return nil, errors.Wrap(, "check")
	}
	return , nil
}

// AcceptTOS accepts version of Terms Of Service.
func ( *Client) ( context.Context,  tg.DataJSON) error {
	,  := .api.HelpAcceptTermsOfService(, )
	return 
}

// SignUp wraps parameters for SignUp.
type SignUp struct {
	PhoneNumber   string
	PhoneCodeHash string
	FirstName     string
	LastName      string
}

// SignUp registers a validated phone number in the system.
//
// To obtain codeHash, use SendCode.
// Use AuthFlow helper to handle authentication flow.
func ( *Client) ( context.Context,  SignUp) (*tg.AuthAuthorization, error) {
	,  := .api.AuthSignUp(, &tg.AuthSignUpRequest{
		LastName:      .LastName,
		PhoneCodeHash: .PhoneCodeHash,
		PhoneNumber:   .PhoneNumber,
		FirstName:     .FirstName,
	})
	if  != nil {
		return nil, errors.Wrap(, "request")
	}
	,  := checkResult()
	if  != nil {
		return nil, errors.Wrap(, "check")
	}
	return , nil
}