package helpers

import (
	
	
	
	
)

type AsciiSearchValues struct {
	// each ascii byte is represented by a bit in this array
	// there are 128bits here and ascii has 128 possible chars
	set [2]uint64
}

func ( string) AsciiSearchValues {
	// pre-calc ascii table stuff to make this go faster
	 := AsciiSearchValues{}
	for  := 0;  < len(); ++ {
		 := []
		if  > unicode.MaxASCII {
			// a bug got us here. that's bad.
			panic(fmt.Errorf("non-ascii value found in ascii search values: %s", ))
		}
		 :=  / 64
		 :=  % 64
		.set[] |= 1 << 
	}

	return 
}

// return the first index of our original vals values within the slice given
func ( AsciiSearchValues) ( []rune) int {
	for  := 0;  < len(); ++ {
		 := []
		if  > unicode.MaxASCII {
			continue
		}
		 :=  / 64
		 :=  % 64
		if .set[]&(1<<) != 0 {
			return 
		}
	}
	return -1
}

// return the first index of anything except our original vals values within the slice given
func ( AsciiSearchValues) ( []rune) int {
	for  := 0;  < len(); ++ {
		 := []
		if  > unicode.MaxASCII {
			return 
		}
		 :=  / 64
		 :=  % 64
		if .set[]&(1<<) == 0 {
			return 
		}
	}
	return -1
}

// return the last index of our original vals values within the slice given
func ( AsciiSearchValues) ( []rune) int {
	panic("not implemented")
	//TODO: this
}

// return the last index of our original vals values within the slice given
func ( AsciiSearchValues) ( []rune) int {
	panic("not implemented")
	//TODO: this
}

type RuneSearchValues struct {
	vals []rune
}

func newRuneSearchValues( []rune) RuneSearchValues {
	//TODO: pre-calc the stuff we need to make each IndexOf go faster
	return RuneSearchValues{vals: }

}

func ( string) RuneSearchValues {
	return newRuneSearchValues([]rune())
}

// return the first index of our original vals values within the slice given
func ( RuneSearchValues) ( []rune) int {
	//naive implementation
	//TODO: this
	return IndexOfAny(, .vals)
}

// return the first index of our original vals values within the slice given
func ( RuneSearchValues) ( []rune) int {
	//TODO: this
	return IndexOfAnyExcept(, .vals)
}

// return the last index of our original vals values within the slice given
func ( RuneSearchValues) ( []rune) int {
	panic("not implemented")
}

// return the last index of our original vals values within the slice given
func ( RuneSearchValues) ( []rune) int {
	panic("not implemented")
	//TODO: this
}

type StringSearchValues struct {
	vals        [][]rune
	ignoreCase  bool
	shortestVal int

	firstChars RuneSearchValues
}

func ( [][]rune,  bool) StringSearchValues {
	 := math.MaxInt
	 := make([]rune, 0, len())
	for ,  := range  {
		if  > len() {
			 = len()
		}
		if !slices.Contains(, [0]) {
			 = append(, [0])
			if  && [0] != unicode.ToUpper([0]) {
				//if we're ignoring case and this letter is impacted by case, add it to our set
				 = append(, unicode.ToUpper([0]))
			}
		}
	}

	return StringSearchValues{
		vals:        ,
		ignoreCase:  ,
		shortestVal: ,
		firstChars:  newRuneSearchValues(),
	}
}

func ( StringSearchValues) ( []rune) int {
	panic("not implemented")
}

func ( StringSearchValues) ( []rune) int {
	panic("not implemented")
}

func ( StringSearchValues) ( []rune) int {
	// go through our input once
	 := len() - .shortestVal
	for  := 0;  <= ; ++ {
		// check if the char are in our starting chars
		 := .firstChars.IndexOfAny([:])
		// first chars not found at all
		if  < 0 {
			return -1
		}
		 += 
		// found a first char, do our full search through each item
		for ,  := range .vals {
			if len()- >= len() && Equals(, , len(), ) {
				return 
			}
			if .ignoreCase && len()- >= len() && EqualsIgnoreCase(, , len(), ) {
				return 
			}
		}
		//skip ahead
		 = 
	}

	return -1
}