package auth

import (
	
	
	

	

	
	
	
)

// PasswordHash computes password hash to log in.
//
// See https://core.telegram.org/api/srp#checking-the-password-with-srp.
func (
	 []byte,
	 int64,
	,  []byte,
	 tg.PasswordKdfAlgoClass,
) (*tg.InputCheckPasswordSRP, error) {
	 := srp.NewSRP(crypto.DefaultRand())

	,  := .(*tg.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow)
	if ! {
		return nil, errors.Errorf("unsupported algo: %T", )
	}

	,  := .Hash(, , , srp.Input(*))
	if  != nil {
		return nil, errors.Wrap(, "create SRP answer")
	}

	return &tg.InputCheckPasswordSRP{
		SRPID: ,
		A:     .A,
		M1:    .M1,
	}, nil
}

// NewPasswordHash computes new password hash to update password.
//
// Notice that NewPasswordHash mutates given alg.
//
// See https://core.telegram.org/api/srp#setting-a-new-2fa-password.
func (
	 []byte,
	 *tg.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow,
) ( []byte,  error) {
	 := srp.NewSRP(crypto.DefaultRand())

	, ,  := .NewHash(, srp.Input(*))
	if  != nil {
		return nil, errors.Wrap(, "create SRP answer")
	}
	.Salt1 = 

	return , nil
}

var (
	emptyPassword tg.InputCheckPasswordSRPClass = &tg.InputCheckPasswordEmpty{}
)

// UpdatePasswordOptions is options structure for UpdatePassword.
type UpdatePasswordOptions struct {
	// Hint is new password hint.
	Hint string
	// Password is password callback.
	//
	// If password was requested and Password is nil, ErrPasswordNotProvided error will be returned.
	Password func(ctx context.Context) (string, error)
}

// UpdatePassword sets new cloud password for this account.
//
// See https://core.telegram.org/api/srp#setting-a-new-2fa-password.
func ( *Client) (
	 context.Context,
	 string,
	 UpdatePasswordOptions,
) error {
	,  := .api.AccountGetPassword()
	if  != nil {
		return errors.Wrap(, "get SRP parameters")
	}

	,  := .NewAlgo.(*tg.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow)
	if ! {
		return errors.Errorf("unsupported algo: %T", .NewAlgo)
	}

	,  := NewPasswordHash([]byte(), )
	if  != nil {
		return errors.Wrap(, "compute new password hash")
	}

	var  = emptyPassword
	if .HasPassword {
		if .Password == nil {
			return ErrPasswordNotProvided
		}

		,  := .Password()
		if  != nil {
			return errors.Wrap(, "get password")
		}

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

	if ,  := .api.AccountUpdatePasswordSettings(, &tg.AccountUpdatePasswordSettingsRequest{
		Password: ,
		NewSettings: tg.AccountPasswordInputSettings{
			NewAlgo:         ,
			NewPasswordHash: ,
			Hint:            .Hint,
		},
	});  != nil {
		return errors.Wrap(, "update password")
	}
	return nil
}

// ResetFailedWaitError reports that you recently requested a password reset that was cancel and need to wait until the
// specified date before requesting another reset.
type ResetFailedWaitError struct {
	Result tg.AccountResetPasswordFailedWait
}

// Until returns time required to wait.
func ( ResetFailedWaitError) () time.Duration {
	 := time.Unix(int64(.Result.RetryDate), 0)
	return time.Until()
}

// Error implements error.
func ( *ResetFailedWaitError) () string {
	return fmt.Sprintf("wait to reset password (%s)", .Until())
}

// ResetPassword resets cloud password and returns time to wait until reset be performed.
// If time is zero, password was successfully reset.
//
// May return ResetFailedWaitError.
//
// See https://core.telegram.org/api/srp#password-reset.
func ( *Client) ( context.Context) (time.Time, error) {
	,  := .api.AccountResetPassword()
	if  != nil {
		return time.Time{}, errors.Wrap(, "reset password")
	}
	switch v := .(type) {
	case *tg.AccountResetPasswordFailedWait:
		return time.Time{}, &ResetFailedWaitError{Result: *}
	case *tg.AccountResetPasswordRequestedWait:
		return time.Unix(int64(.UntilDate), 0), nil
	case *tg.AccountResetPasswordOk:
		return time.Time{}, nil
	default:
		return time.Time{}, errors.Errorf("unexpected type %T", )
	}
}

// CancelPasswordReset cancels password reset.
//
// See https://core.telegram.org/api/srp#password-reset.
func ( *Client) ( context.Context) error {
	if ,  := .api.AccountDeclinePasswordReset();  != nil {
		return errors.Wrap(, "cancel password reset")
	}
	return nil
}