package jwt

import (
	
	
	
	
)

type Parser struct {
	// If populated, only these methods will be considered valid.
	//
	// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
	ValidMethods []string

	// Use JSON Number format in JSON decoder.
	//
	// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
	UseJSONNumber bool

	// Skip claims validation during token parsing.
	//
	// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
	SkipClaimsValidation bool
}

// NewParser creates a new Parser with the specified options
func ( ...ParserOption) *Parser {
	 := &Parser{}

	// loop through our parsing options and apply them
	for ,  := range  {
		()
	}

	return 
}

// Parse parses, validates, verifies the signature and returns the parsed token.
// keyFunc will receive the parsed token and should return the key for validating.
func ( *Parser) ( string,  Keyfunc) (*Token, error) {
	return .ParseWithClaims(, MapClaims{}, )
}

// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object implementing the Claims
// interface. This provides default values which can be overridden and allows a caller to use their own type, rather
// than the default MapClaims implementation of Claims.
//
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
func ( *Parser) ( string,  Claims,  Keyfunc) (*Token, error) {
	, ,  := .ParseUnverified(, )
	if  != nil {
		return , 
	}

	// Verify signing method is in the required set
	if .ValidMethods != nil {
		var  = false
		var  = .Method.Alg()
		for ,  := range .ValidMethods {
			if  ==  {
				 = true
				break
			}
		}
		if ! {
			// signing method is not in the listed set
			return , NewValidationError(fmt.Sprintf("signing method %v is invalid", ), ValidationErrorSignatureInvalid)
		}
	}

	// Lookup key
	var  interface{}
	if  == nil {
		// keyFunc was not provided.  short circuiting validation
		return , NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable)
	}
	if ,  = ();  != nil {
		// keyFunc returned an error
		if ,  := .(*ValidationError);  {
			return , 
		}
		return , &ValidationError{Inner: , Errors: ValidationErrorUnverifiable}
	}

	 := &ValidationError{}

	// Validate Claims
	if !.SkipClaimsValidation {
		if  := .Claims.Valid();  != nil {

			// If the Claims Valid returned an error, check if it is a validation error,
			// If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set
			if ,  := .(*ValidationError); ! {
				 = &ValidationError{Inner: , Errors: ValidationErrorClaimsInvalid}
			} else {
				 = 
			}
		}
	}

	// Perform validation
	.Signature = [2]
	if  = .Method.Verify(strings.Join([0:2], "."), .Signature, );  != nil {
		.Inner = 
		.Errors |= ValidationErrorSignatureInvalid
	}

	if .valid() {
		.Valid = true
		return , nil
	}

	return , 
}

// ParseUnverified parses the token but doesn't validate the signature.
//
// WARNING: Don't use this method unless you know what you're doing.
//
// It's only ever useful in cases where you know the signature is valid (because it has
// been checked previously in the stack) and you want to extract values from it.
func ( *Parser) ( string,  Claims) ( *Token,  []string,  error) {
	 = strings.Split(, ".")
	if len() != 3 {
		return nil, , NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed)
	}

	 = &Token{Raw: }

	// parse Header
	var  []byte
	if ,  = DecodeSegment([0]);  != nil {
		if strings.HasPrefix(strings.ToLower(), "bearer ") {
			return , , NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed)
		}
		return , , &ValidationError{Inner: , Errors: ValidationErrorMalformed}
	}
	if  = json.Unmarshal(, &.Header);  != nil {
		return , , &ValidationError{Inner: , Errors: ValidationErrorMalformed}
	}

	// parse Claims
	var  []byte
	.Claims = 

	if ,  = DecodeSegment([1]);  != nil {
		return , , &ValidationError{Inner: , Errors: ValidationErrorMalformed}
	}
	 := json.NewDecoder(bytes.NewBuffer())
	if .UseJSONNumber {
		.UseNumber()
	}
	// JSON Decode.  Special case for map type to avoid weird pointer behavior
	if ,  := .Claims.(MapClaims);  {
		 = .Decode(&)
	} else {
		 = .Decode(&)
	}
	// Handle decode error
	if  != nil {
		return , , &ValidationError{Inner: , Errors: ValidationErrorMalformed}
	}

	// Lookup signature method
	if ,  := .Header["alg"].(string);  {
		if .Method = GetSigningMethod(); .Method == nil {
			return , , NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable)
		}
	} else {
		return , , NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable)
	}

	return , , nil
}