package yu_proto

import (
	yu_strconv "gogs.qqck.cn/s/tools/strconv"
)

func (t *Protobuf) SetBool(value bool, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetByte(value byte, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetInt8(value int8, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetUint8(value uint8, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetInt16(value int16, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetUint16(value uint16, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetInt32(value int32, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetUint32(value uint32, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetInt64(value int64, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetUint64(value uint64, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetFloat32(value float32, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetFloat64(value float64, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	t.set(value, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetString(value string, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	j_buf := make([]byte, len(value))
	copy(j_buf, value)
	t.set(j_buf, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) SetBytes(value []byte, ids ...any) *Protobuf {
	if len(ids) == 0 {
		return t
	}
	j_buf := make([]byte, len(value))
	copy(j_buf, value)
	t.set(j_buf, ids, 0, nil, t.list)
	return t
}

func (t *Protobuf) set(value any, ids []any, idi int, parent *node, list *node) {
	// 判断是否会有子链表
	if j_idi := idi + 1; j_idi < len(ids) {
		var j_i int
		switch j_id := ids[idi].(type) {
		case string:
			if j_id := yu_strconv.ParseUint64(j_id); j_id < 1 {
				return
			} else {
				var j_prev *node
				for {
					// 寻找同id节点
					if list.id == j_id {
						switch list.value.(type) {
						case *node:
							// 是链表结构，无需操作
							t.set(value, ids, j_idi, list, list.value.(*node))
						case *[]*node:
							// 是数组结构，无需操作
							t.set(value, ids, j_idi, list, nil)
						default:
							// 非链表结构，改变其值为链表
							list.value = &node{}
							t.set(value, ids, j_idi, list, list.value.(*node))
						}
						return
					}
					// 判断是否插入节点
					if list.id > j_id {
						// 判断是否为首节点
						if j_prev == nil {
							list._next = &node{list._next, list.id, list.value}
							list.id, list.value = j_id, &node{}
							t.set(value, ids, j_idi, list, list.value.(*node))
						} else {
							j_prev._next = &node{list, j_id, &node{}}
							t.set(value, ids, j_idi, j_prev._next, j_prev._next.value.(*node))
						}
						return
					}
					// 判断是否到链表尾部
					if list._next == nil {
						// 判断当前节点是否为空节点
						if list.id == 0 {
							// 空节点就直接赋值
							list.id, list.value = j_id, &node{}
							t.set(value, ids, j_idi, list, list.value.(*node))
						} else {
							// 创建新节点
							list._next = &node{nil, j_id, &node{}}
							t.set(value, ids, j_idi, list._next, list._next.value.(*node))
						}
						return
					}
					j_prev, list = list, list._next
				}
			}
		case int8:
			j_i = int(j_id)
		case uint8:
			j_i = int(j_id)
		case int16:
			j_i = int(j_id)
		case uint16:
			j_i = int(j_id)
		case int32:
			j_i = int(j_id)
		case uint32:
			j_i = int(j_id)
		case int64:
			j_i = int(j_id)
		case uint64:
			j_i = int(j_id)
		case int:
			j_i = j_id
		case uint:
			j_i = int(j_id)
		case uintptr:
			j_i = int(j_id)
		default:
			return
		}
		if j_i < 0 {
			return
		}
		if parent == nil {
			// 数组必须有一个父节点
			return
		}
		var j_array *[]*node
		switch parent.value.(type) {
		case *[]*node:
			// 是数组结构
			j_array = parent.value.(*[]*node)
			// 数组容量不足索引时扩充数组
			for len(*j_array) < j_i+1 {
				*j_array = append(*j_array, nil)
			}
		default:
			// 非数组结构，改变其值为数组
			j_tmp := make([]*node, j_i+1)
			j_array, parent.value = &j_tmp, &j_tmp
		}
		if (*j_array)[j_i] == nil {
			(*j_array)[j_i] = &node{}
		}
		if (*j_array)[j_i].value == nil {
			(*j_array)[j_i]._next, (*j_array)[j_i].id, (*j_array)[j_i].value = nil, 0, &node{}
		}
		switch (*j_array)[j_i].value.(type) {
		case *node:
			// 是链表结构，无需操作
		default:
			(*j_array)[j_i]._next, (*j_array)[j_i].id, (*j_array)[j_i].value = nil, 0, &node{}
		}
		t.set(value, ids, j_idi, (*j_array)[j_i], (*j_array)[j_i].value.(*node))
		return
	}
	// 最后一层链表
	var j_i int
	switch j_id := ids[idi].(type) {
	case string:
		if j_id := yu_strconv.ParseUint64(j_id); j_id < 1 {
			return
		} else {
			var j_prev *node
			for {
				// 寻找同id节点
				if list.id == j_id {
					list.value = value
					return
				}
				// 判断是否插入节点
				if list.id > j_id {
					// 判断是否为首节点
					if j_prev == nil {
						list._next = &node{list._next, list.id, list.value}
						list.id, list.value = j_id, value
					} else {
						j_prev._next = &node{list, j_id, value}
					}
					return
				}
				// 判断是否到链表尾部
				if list._next == nil {
					// 判断当前节点是否为空节点
					if list.id == 0 {
						// 空节点就直接赋值
						list.id, list.value = j_id, value
					} else {
						// 创建新节点
						list._next = &node{nil, j_id, value}
					}
					return
				}
				j_prev, list = list, list._next
			}
		}
	case int8:
		j_i = int(j_id)
	case uint8:
		j_i = int(j_id)
	case int16:
		j_i = int(j_id)
	case uint16:
		j_i = int(j_id)
	case int32:
		j_i = int(j_id)
	case uint32:
		j_i = int(j_id)
	case int64:
		j_i = int(j_id)
	case uint64:
		j_i = int(j_id)
	case int:
		j_i = j_id
	case uint:
		j_i = int(j_id)
	case uintptr:
		j_i = int(j_id)
	default:
		return
	}
	if j_i < 0 {
		return
	}
	if parent == nil {
		// 数组必须有一个父节点
		return
	}
	var j_array *[]*node
	switch parent.value.(type) {
	case *[]*node:
		// 是数组结构
		j_array = parent.value.(*[]*node)
		// 数组容量不足索引时扩充数组
		for len(*j_array) < j_i+1 {
			*j_array = append(*j_array, nil)
		}
	default:
		// 非数组结构，改变其值为数组
		j_tmp := make([]*node, j_i+1)
		j_array, parent.value = &j_tmp, &j_tmp
	}
	if (*j_array)[j_i] == nil {
		(*j_array)[j_i] = &node{}
	}
	(*j_array)[j_i]._next, (*j_array)[j_i].id, (*j_array)[j_i].value = nil, 0, value
	return
}
