package goja

import (
	
	

	
)

type objectGoArrayReflect struct {
	objectGoReflect
	lengthProp valueProperty

	valueCache valueArrayCache

	putIdx func(idx int, v Value, throw bool) bool
}

type valueArrayCache []reflectValueWrapper

func ( *valueArrayCache) ( int) reflectValueWrapper {
	if  < len(*) {
		return (*)[]
	}
	return nil
}

func ( *valueArrayCache) ( int) {
	 := cap(*)
	if  <  {
		 := make([]reflectValueWrapper, , growCap(, len(*), ))
		copy(, *)
		* = 
	} else {
		* = (*)[:]
	}
}

func ( *valueArrayCache) ( int,  reflectValueWrapper) {
	if len(*) <=  {
		.grow( + 1)
	}
	(*)[] = 
}

func ( *valueArrayCache) ( int) {
	if len(*) >  {
		 := (*)[:]
		for ,  := range  {
			if  != nil {
				copyReflectValueWrapper()
				[] = nil
			}
		}
		* = (*)[:]
	}
}

func ( *objectGoArrayReflect) () {
	.objectGoReflect.init()
	.class = classArray
	.prototype = .val.runtime.getArrayPrototype()
	.baseObject._put("length", &.lengthProp)
}

func ( *objectGoArrayReflect) () {
	._init()
	.updateLen()
	.putIdx = ._putIdx
}

func ( *objectGoArrayReflect) () {
	.lengthProp.value = intToValue(int64(.fieldsValue.Len()))
}

func ( *objectGoArrayReflect) ( valueInt) bool {
	if  := int64();  >= 0 &&  < int64(.fieldsValue.Len()) {
		return true
	}
	return false
}

func ( *objectGoArrayReflect) ( unistring.String) bool {
	if  := strToIdx64();  >= 0 &&  < int64(.fieldsValue.Len()) {
		return true
	}
	return false
}

func ( *objectGoArrayReflect) ( int) Value {
	if  := .valueCache.get();  != nil {
		return .esValue()
	}

	 := .fieldsValue.Index()

	,  := .elemToValue()
	if  != nil {
		.valueCache.put(, )
	}

	return 
}

func ( *objectGoArrayReflect) ( valueInt,  Value) Value {
	if  := toIntStrict(int64());  >= 0 &&  < .fieldsValue.Len() {
		return ._getIdx()
	}
	return .objectGoReflect.getStr(.string(), )
}

func ( *objectGoArrayReflect) ( unistring.String,  Value) Value {
	var  Value
	if  := strToGoIdx();  >= 0 &&  < .fieldsValue.Len() {
		 = ._getIdx()
	} else if  == "length" {
		if .fieldsValue.Kind() == reflect.Slice {
			.updateLen()
		}
		 = &.lengthProp
	} else {
		 = .objectGoReflect.getOwnPropStr()
	}
	return .getStrWithOwnProp(, , )
}

func ( *objectGoArrayReflect) ( unistring.String) Value {
	if  := strToGoIdx();  >= 0 {
		if  < .fieldsValue.Len() {
			return &valueProperty{
				value:      ._getIdx(),
				writable:   true,
				enumerable: true,
			}
		}
		return nil
	}
	if  == "length" {
		if .fieldsValue.Kind() == reflect.Slice {
			.updateLen()
		}
		return &.lengthProp
	}
	return .objectGoReflect.getOwnPropStr()
}

func ( *objectGoArrayReflect) ( valueInt) Value {
	if  := toIntStrict(int64());  >= 0 &&  < .fieldsValue.Len() {
		return &valueProperty{
			value:      ._getIdx(),
			writable:   true,
			enumerable: true,
		}
	}
	return nil
}

func ( *objectGoArrayReflect) ( int,  Value,  bool) bool {
	 := .valueCache.get()
	if  != nil {
		copyReflectValueWrapper()
	}

	 := .fieldsValue.Index()
	 := .val.runtime.toReflectValue(, , &objectExportCtx{})
	if  != nil {
		if  != nil {
			.setReflectValue()
		}
		.val.runtime.typeErrorResult(, "Go type conversion error: %v", )
		return false
	}
	if  != nil {
		.valueCache[] = nil
	}
	return true
}

func ( *objectGoArrayReflect) ( valueInt,  Value,  bool) bool {
	if  := toIntStrict(int64());  >= 0 {
		if  >= .fieldsValue.Len() {
			if ,  := ._setForeignIdx(, nil, , .val, );  {
				return 
			}
		}
		return .putIdx(, , )
	} else {
		 := .string()
		if ,  := ._setForeignStr(, nil, , .val, ); ! {
			.val.runtime.typeErrorResult(, "Can't set property '%s' on Go slice", )
			return false
		} else {
			return 
		}
	}
}

func ( *objectGoArrayReflect) ( unistring.String,  Value,  bool) bool {
	if  := strToGoIdx();  >= 0 {
		if  >= .fieldsValue.Len() {
			if ,  := ._setForeignStr(, nil, , .val, );  {
				return 
			}
		}
		return .putIdx(, , )
	} else {
		if ,  := ._setForeignStr(, nil, , .val, ); ! {
			.val.runtime.typeErrorResult(, "Can't set property '%s' on Go slice", )
			return false
		} else {
			return 
		}
	}
}

func ( *objectGoArrayReflect) ( valueInt, ,  Value,  bool) (bool, bool) {
	return ._setForeignIdx(, trueValIfPresent(._hasIdx()), , , )
}

func ( *objectGoArrayReflect) ( unistring.String, ,  Value,  bool) (bool, bool) {
	return ._setForeignStr(, trueValIfPresent(.hasOwnPropertyStr()), , , )
}

func ( *objectGoArrayReflect) ( valueInt) bool {
	return ._hasIdx()
}

func ( *objectGoArrayReflect) ( unistring.String) bool {
	if ._hasStr() ||  == "length" {
		return true
	}
	return .objectGoReflect.hasOwnPropertyStr()
}

func ( *objectGoArrayReflect) ( valueInt,  PropertyDescriptor,  bool) bool {
	if  := toIntStrict(int64());  >= 0 {
		if !.val.runtime.checkHostObjectPropertyDescr(.string(), , ) {
			return false
		}
		 := .Value
		if  == nil {
			 = _undefined
		}
		return .putIdx(, , )
	}
	.val.runtime.typeErrorResult(, "Cannot define property '%d' on a Go slice", )
	return false
}

func ( *objectGoArrayReflect) ( unistring.String,  PropertyDescriptor,  bool) bool {
	if  := strToGoIdx();  >= 0 {
		if !.val.runtime.checkHostObjectPropertyDescr(, , ) {
			return false
		}
		 := .Value
		if  == nil {
			 = _undefined
		}
		return .putIdx(, , )
	}
	.val.runtime.typeErrorResult(, "Cannot define property '%s' on a Go slice", )
	return false
}

func ( *objectGoArrayReflect) ( int) {
	if  < .fieldsValue.Len() {
		if  := .valueCache.get();  != nil {
			copyReflectValueWrapper()
			.valueCache[] = nil
		}

		.fieldsValue.Index().Set(reflect.Zero(.fieldsValue.Type().Elem()))
	}
}

func ( *objectGoArrayReflect) ( unistring.String,  bool) bool {
	if  := strToGoIdx();  >= 0 {
		._deleteIdx()
		return true
	}

	return .objectGoReflect.deleteStr(, )
}

func ( *objectGoArrayReflect) ( valueInt,  bool) bool {
	 := toIntStrict(int64())
	if  >= 0 {
		._deleteIdx()
	}
	return true
}

type goArrayReflectPropIter struct {
	o          *objectGoArrayReflect
	idx, limit int
}

func ( *goArrayReflectPropIter) () (propIterItem, iterNextFunc) {
	if .idx < .limit && .idx < .o.fieldsValue.Len() {
		 := strconv.Itoa(.idx)
		.idx++
		return propIterItem{name: asciiString(), enumerable: _ENUM_TRUE}, .
	}

	return .o.objectGoReflect.iterateStringKeys()()
}

func ( *objectGoArrayReflect) ( bool,  []Value) []Value {
	for  := 0;  < .fieldsValue.Len(); ++ {
		 = append(, asciiString(strconv.Itoa()))
	}

	return .objectGoReflect.stringKeys(, )
}

func ( *objectGoArrayReflect) () iterNextFunc {
	return (&goArrayReflectPropIter{
		o:     ,
		limit: .fieldsValue.Len(),
	}).next
}

func ( *objectGoArrayReflect) () int {
	return .fieldsValue.Len()
}

func ( *objectGoArrayReflect) ( int) Value {
	return .getIdx(valueInt(), nil)
}

func ( *objectGoArrayReflect) ( int,  int) {
	 := .fieldsValue.Index()
	 := .fieldsValue.Index()
	 := reflect.New(.fieldsValue.Type().Elem()).Elem()
	.Set()
	.Set()
	.Set()

	 := .valueCache.get()
	 := .valueCache.get()
	if  != nil {
		.setReflectValue()
		.valueCache.put(, )
	} else {
		if  < len(.valueCache) {
			.valueCache[] = nil
		}
	}

	if  != nil {
		.setReflectValue()
		.valueCache.put(, )
	} else {
		if  < len(.valueCache) {
			.valueCache[] = nil
		}
	}
}