package goja

import 

type argumentsObject struct {
	baseObject
	length int
}

type mappedProperty struct {
	valueProperty
	v *Value
}

func ( *argumentsObject) ( unistring.String,  Value) Value {
	return .getStrWithOwnProp(.getOwnPropStr(), , )
}

func ( *argumentsObject) ( unistring.String) Value {
	if ,  := .values[].(*mappedProperty);  {
		if .writable && .enumerable && .configurable {
			return *.v
		}
		return &valueProperty{
			value:        *.v,
			writable:     .writable,
			configurable: .configurable,
			enumerable:   .enumerable,
		}
	}

	return .baseObject.getOwnPropStr()
}

func ( *argumentsObject) () {
	.baseObject.init()
	._putProp("length", intToValue(int64(.length)), true, false, true)
}

func ( *argumentsObject) ( unistring.String,  Value,  bool) bool {
	if ,  := .values[].(*mappedProperty);  {
		if !.writable {
			.val.runtime.typeErrorResult(, "Property is not writable: %s", )
			return false
		}
		*.v = 
		return true
	}
	return .baseObject.setOwnStr(, , )
}

func ( *argumentsObject) ( unistring.String, ,  Value,  bool) (bool, bool) {
	return ._setForeignStr(, .getOwnPropStr(), , , )
}

func ( *argumentsObject) ( unistring.String,  bool) bool {
	if ,  := .values[].(*mappedProperty);  {
		if !.checkDeleteProp(, &.valueProperty, ) {
			return false
		}
		._delete()
		return true
	}

	return .baseObject.deleteStr(, )
}

type argumentsPropIter struct {
	wrapped iterNextFunc
}

func ( *argumentsPropIter) () (propIterItem, iterNextFunc) {
	var  propIterItem
	, .wrapped = .wrapped()
	if .wrapped == nil {
		return propIterItem{}, nil
	}
	if ,  := .value.(*mappedProperty);  {
		.value = *.v
	}
	return , .
}

func ( *argumentsObject) () iterNextFunc {
	return (&argumentsPropIter{
		wrapped: .baseObject.iterateStringKeys(),
	}).next
}

func ( *argumentsObject) ( unistring.String,  PropertyDescriptor,  bool) bool {
	if ,  := .values[].(*mappedProperty);  {
		 := &valueProperty{
			configurable: .configurable,
			writable:     true,
			enumerable:   .enumerable,
			value:        *.v,
		}

		,  := .baseObject._defineOwnProperty(, , , )
		if ! {
			return false
		}

		if ,  := .(*valueProperty);  {
			if !.accessor {
				*.v = .value
			}
			if .accessor || !.writable {
				._put(, )
				return true
			}
			.configurable = .configurable
			.enumerable = .enumerable
		} else {
			*.v = 
			.configurable = true
			.enumerable = true
		}

		return true
	}

	return .baseObject.defineOwnPropertyStr(, , )
}

func ( *argumentsObject) ( *objectExportCtx) interface{} {
	if ,  := .get(.val);  {
		return 
	}
	 := make([]interface{}, .length)
	.put(.val, )
	for  := range  {
		 := .getIdx(valueInt(int64()), nil)
		if  != nil {
			[] = exportValue(, )
		}
	}
	return 
}