package telegram

import (
	
	
	
	
	
	

	
	
	
	

	
	
	
	
	
	
)

func () (string, error) {
	,  := os.LookupEnv("SESSION_DIR")
	if  {
		return filepath.Abs()
	}

	,  := os.UserHomeDir()
	if  != nil {
		 = "."
	}

	return filepath.Abs(filepath.Join(, ".td"))
}

// OptionsFromEnvironment fills unfilled field in opts parameter
// using environment variables.
//
// Variables:
//
//	SESSION_FILE:        path to session file
//	SESSION_DIR:         path to session directory, if SESSION_FILE is not set
//	ALL_PROXY, NO_PROXY: see https://pkg.go.dev/golang.org/x/net/proxy#FromEnvironment
func ( Options) (Options, error) {
	// Setting up session storage if not provided.
	if .SessionStorage == nil {
		,  := os.LookupEnv("SESSION_FILE")
		if ! {
			,  := sessionDir()
			if  != nil {
				return Options{}, errors.Wrap(, "SESSION_DIR not set or invalid")
			}
			 = filepath.Join(, "session.json")
		}

		,  := filepath.Split()
		if  := os.MkdirAll(, 0700);  != nil {
			return Options{}, errors.Wrap(, "session dir creation")
		}

		.SessionStorage = &session.FileStorage{
			Path: ,
		}
	}

	if .Resolver == nil {
		.Resolver = dcs.Plain(dcs.PlainOptions{
			Dial: proxy.Dial,
		})
	}

	return , nil
}

// ClientFromEnvironment creates client using OptionsFromEnvironment
// but does not connect to server.
//
// Variables:
//
//	APP_ID:   app_id of Telegram app.
//	APP_HASH: app_hash of Telegram app.
func ( Options) (*Client, error) {
	,  := strconv.Atoi(os.Getenv("APP_ID"))
	if  != nil {
		return nil, errors.Wrap(, "APP_ID not set or invalid")
	}

	 := os.Getenv("APP_HASH")
	if  == "" {
		return nil, errors.New("no APP_HASH provided")
	}

	,  = OptionsFromEnvironment()
	if  != nil {
		return nil, 
	}

	return NewClient(, , ), nil
}

func ( context.Context,  *zap.Logger,  func( context.Context) error) error {
	 := backoff.WithContext(backoff.NewExponentialBackOff(), )

	// List of known retryable RPC error types.
	 := []string{
		"NEED_MEMBER_INVALID",
		"AUTH_KEY_UNREGISTERED",
		"API_ID_PUBLISHED_FLOOD",
	}

	return backoff.Retry(func() error {
		if  := ();  != nil {
			.Warn("TestClient run failed", zap.Error())

			if tgerr.Is(, ...) {
				return 
			}
			if ,  := AsFloodWait();  {
				 := clock.System.Timer( + 1*time.Second)
				defer clock.StopTimer()

				select {
				case <-.C():
					return 
				case <-.Done():
					return .Err()
				}
			}
			if errors.Is(, io.EOF) || errors.Is(, io.ErrUnexpectedEOF) {
				// Possibly server closed connection.
				return 
			}

			return backoff.Permanent()
		}

		return nil
	}, )
}

// TestClient creates and authenticates user telegram.Client
// using Telegram test server.
func ( context.Context,  Options,  func( context.Context,  *Client) error) error {
	if .DC == 0 {
		.DC = 2
	}
	if .DCList.Zero() {
		.DCList = dcs.Test()
	}

	 := zap.NewNop()
	if .Logger != nil {
		 = .Logger.Named("test")
	}

	// Sometimes testing server can return "AUTH_KEY_UNREGISTERED" error.
	// It is expected and client implementation is unlikely to cause
	// such errors, so just doing retries using backoff.
	return retry(, , func( context.Context) error {
		 := NewClient(TestAppID, TestAppHash, )
		return .Run(, func( context.Context) error {
			if  := .Auth().IfNecessary(, auth.NewFlow(
				auth.Test(crypto.DefaultRand(), .DC),
				auth.SendCodeOptions{},
			));  != nil {
				return errors.Wrap(, "auth flow")
			}

			return (, )
		})
	})
}