package redis

import (
	
	
	
	
	
)

type scripter interface {
	Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
	EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
	ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
	ScriptLoad(ctx context.Context, script string) *StringCmd
}

var (
	_ scripter = (*Client)(nil)
	_ scripter = (*Ring)(nil)
	_ scripter = (*ClusterClient)(nil)
)

type Script struct {
	src, hash string
}

func ( string) *Script {
	 := sha1.New()
	_, _ = io.WriteString(, )
	return &Script{
		src:  ,
		hash: hex.EncodeToString(.Sum(nil)),
	}
}

func ( *Script) () string {
	return .hash
}

func ( *Script) ( context.Context,  scripter) *StringCmd {
	return .ScriptLoad(, .src)
}

func ( *Script) ( context.Context,  scripter) *BoolSliceCmd {
	return .ScriptExists(, .hash)
}

func ( *Script) ( context.Context,  scripter,  []string,  ...interface{}) *Cmd {
	return .Eval(, .src, , ...)
}

func ( *Script) ( context.Context,  scripter,  []string,  ...interface{}) *Cmd {
	return .EvalSha(, .hash, , ...)
}
Run optimistically uses EVALSHA to run the script. If script does not exist it is retried using EVAL.
func ( *Script) ( context.Context,  scripter,  []string,  ...interface{}) *Cmd {
	 := .EvalSha(, , , ...)
	if  := .Err();  != nil && strings.HasPrefix(.Error(), "NOSCRIPT ") {
		return .Eval(, , , ...)
	}
	return