package vals

import (
	
	
	

	
)

var (
	errIndexMustBeInteger = errors.New("index must must be integer")
)

func ( List,  interface{}) (interface{}, error) {
	,  := ConvertListIndex(, .Len())
	if  != nil {
		return nil, 
	}
	if .Slice {
		return .SubVector(.Lower, .Upper), nil
	}
	// Bounds are already checked.
	,  := .Index(.Lower)
	return , nil
}

// ListIndex represents a (converted) list index.
type ListIndex struct {
	Slice bool
	Lower int
	Upper int
}

func (,  int,  bool) (int, error) {
	if  < 0 {
		if  < - {
			return 0, negIndexOutOfRange(strconv.Itoa(), )
		}
		return  + , nil
	}
	if  {
		if  >  {
			return 0, posIndexOutOfRange(strconv.Itoa(), +1)
		}
	} else {
		if  >=  {
			return 0, posIndexOutOfRange(strconv.Itoa(), )
		}
	}
	return , nil
}

// ConvertListIndex parses a list index, check whether it is valid, and returns
// the converted structure.
func ( interface{},  int) (*ListIndex, error) {
	switch rawIndex := .(type) {
	case int:
		,  := adjustAndCheckIndex(, , false)
		if  != nil {
			return nil, 
		}
		return &ListIndex{false, , 0}, nil
	case string:
		, , ,  := parseIndexString(, )
		if  != nil {
			return nil, 
		}
		if ! {
			,  = adjustAndCheckIndex(, , false)
			if  != nil {
				return nil, 
			}
		} else {
			,  = adjustAndCheckIndex(, , true)
			if  != nil {
				return nil, 
			}
			 := 
			,  = adjustAndCheckIndex(, , true)
			if  != nil {
				return nil, 
			}
			if  <  {
				if  < 0 {
					return nil, errs.OutOfRange{
						What:     "negative slice upper index here",
						ValidLow: strconv.Itoa( - ), ValidHigh: "-1",
						Actual: strconv.Itoa()}
				}
				return nil, errs.OutOfRange{
					What:     "slice upper index here",
					ValidLow: strconv.Itoa(), ValidHigh: strconv.Itoa(),
					Actual: strconv.Itoa()}
			}
		}
		return &ListIndex{, , }, nil
	default:
		return nil, errIndexMustBeInteger
	}
}

// Index = Number |
//         Number ( ':' | '..' | '..=' ) Number
func ( string,  int) ( bool,  int,  int,  error) {
	, ,  := splitIndexString()
	if  == "" {
		// A single number
		,  := atoi(, )
		if  != nil {
			return false, 0, 0, 
		}
		return false, , 0, nil
	}
	if  == "" {
		 = 0
	} else {
		,  = atoi(, )
		if  != nil {
			return false, 0, 0, 
		}
	}
	if  == "" {
		 = 
	} else {
		,  = atoi(, )
		if  != nil {
			return false, 0, 0, 
		}
		if  == "..=" {
			++
		}
	}
	// Two numbers
	return true, , , nil
}

func ( string) (, ,  string) {
	if  := strings.IndexRune(, ':');  >= 0 {
		return [:], ":", [+1:]
	}
	if  := strings.Index(, "..=");  >= 0 {
		return [:], "..=", [+3:]
	}
	if  := strings.Index(, "..");  >= 0 {
		return [:], "..", [+2:]
	}
	return , "", ""
}

// atoi is a wrapper around strconv.Atoi, converting strconv.ErrRange to
// errs.OutOfRange.
func ( string,  int) (int, error) {
	,  := strconv.Atoi()
	if  != nil {
		if .(*strconv.NumError).Err == strconv.ErrRange {
			if  < 0 {
				return 0, negIndexOutOfRange(, )
			}
			return 0, posIndexOutOfRange(, )
		}
		return 0, errIndexMustBeInteger
	}
	return , nil
}

func ( string,  int) errs.OutOfRange {
	return errs.OutOfRange{
		What:     "index here",
		ValidLow: "0", ValidHigh: strconv.Itoa( - 1), Actual: }
}

func ( string,  int) errs.OutOfRange {
	return errs.OutOfRange{
		What:     "negative index here",
		ValidLow: strconv.Itoa(-), ValidHigh: "-1", Actual: }
}