// Code generated by eevee. DO NOT EDIT!

package response

import (
	"api/model"
	"bytes"
	"context"
	"golang.org/x/xerrors"
	"strconv"
)

type UserGetterSubtype struct {
	User   *model.User
	Param1 string
	Param2 int
}

func (r *UserGetterSubtype) ToJSON(ctx context.Context) ([]byte, error) {
	if r == nil {
		return []byte("null"), nil
	}
	if r, ok := interface{}(r).(model.BeforeRenderer); ok {
		if err := r.BeforeRender(ctx); err != nil {
			return nil, xerrors.Errorf("failed to BeforeRender: %w", err)
		}
	}
	buf := []byte{}
	buf = append(buf, '{')
	user := r.User
	userBytes, err := user.ToJSON(ctx)
	if err != nil {
		return nil, xerrors.Errorf("cannot render to JSON: %w", err)
	}
	if !bytes.Equal(userBytes, []byte("null")) {
		buf = append(buf, userBytes[1:len(userBytes)-1]...)
	}
	buf = append(buf, ',')
	buf = append(buf, "\"param1\":"...)
	buf = append(buf, strconv.Quote(r.Param1)...)
	buf = append(buf, ',')
	buf = append(buf, "\"param2\":"...)
	buf = strconv.AppendInt(buf, int64(r.Param2), 10)
	buf = append(buf, '}')
	return buf, nil
}

func (r *UserGetterSubtype) ToJSONWithOption(ctx context.Context, option *model.RenderOption) ([]byte, error) {
	if r == nil {
		return []byte("null"), nil
	}
	if r, ok := interface{}(r).(model.BeforeRenderer); ok {
		if err := r.BeforeRender(ctx); err != nil {
			return nil, xerrors.Errorf("failed to BeforeRender: %w", err)
		}
	}
	buf := []byte{}
	isWritten := false
	buf = append(buf, '{')
	if option.IsIncludeAll {
		user := r.User
		userBytes, err := user.ToJSON(ctx)
		if err != nil {
			return nil, xerrors.Errorf("cannot render to JSON: %w", err)
		}
		if !bytes.Equal(userBytes, []byte("null")) {
			buf = append(buf, userBytes[1:len(userBytes)-1]...)
		}
		isWritten = true
	} else if opt := option.IncludeOption("user"); opt != nil {
		user := r.User
		userBytes, err := user.ToJSONWithOption(ctx, opt)
		if err != nil {
			return nil, xerrors.Errorf("cannot render to JSON: %w", err)
		}
		if !bytes.Equal(userBytes, []byte("null")) {
			buf = append(buf, userBytes[1:len(userBytes)-1]...)
		}
		isWritten = true
	}
	if option.Exists("param_1") {
		if isWritten {
			buf = append(buf, ',')
		}
		buf = append(buf, "\"param1\":"...)
		buf = append(buf, strconv.Quote(r.Param1)...)
		isWritten = true
	}
	if option.Exists("param_2") {
		if isWritten {
			buf = append(buf, ',')
		}
		buf = append(buf, "\"param2\":"...)
		buf = strconv.AppendInt(buf, int64(r.Param2), 10)
		isWritten = true
	}
	buf = append(buf, '}')
	return buf, nil
}

type UserGetter struct {
	Users         *model.Users
	Sub           *UserGetterSubtype
	renderedBytes []byte
}

func (r *UserGetter) ToJSON(ctx context.Context) ([]byte, error) {
	if r == nil {
		return []byte("null"), nil
	}
	if r, ok := interface{}(r).(model.BeforeRenderer); ok {
		if err := r.BeforeRender(ctx); err != nil {
			return nil, xerrors.Errorf("failed to BeforeRender: %w", err)
		}
	}
	buf := []byte{}
	buf = append(buf, '{')
	users := r.Users
	usersBytes, err := users.ToJSON(ctx)
	if err != nil {
		return nil, xerrors.Errorf("cannot render to JSON: %w", err)
	}
	buf = append(buf, "\"users\":"...)
	buf = append(buf, usersBytes...)
	buf = append(buf, ',')
	sub := r.Sub
	subBytes, err := sub.ToJSON(ctx)
	if err != nil {
		return nil, xerrors.Errorf("cannot render to JSON: %w", err)
	}
	buf = append(buf, "\"sub\":"...)
	buf = append(buf, subBytes...)
	buf = append(buf, '}')
	return buf, nil
}

func (r *UserGetter) ToJSONWithOption(ctx context.Context, option *model.RenderOption) ([]byte, error) {
	if r == nil {
		return []byte("null"), nil
	}
	if r, ok := interface{}(r).(model.BeforeRenderer); ok {
		if err := r.BeforeRender(ctx); err != nil {
			return nil, xerrors.Errorf("failed to BeforeRender: %w", err)
		}
	}
	buf := []byte{}
	isWritten := false
	buf = append(buf, '{')
	if option.IsIncludeAll {
		users := r.Users
		usersBytes, err := users.ToJSON(ctx)
		if err != nil {
			return nil, xerrors.Errorf("cannot render to JSON: %w", err)
		}
		buf = append(buf, "\"users\":"...)
		buf = append(buf, usersBytes...)
		isWritten = true
	} else if opt := option.IncludeOption("users"); opt != nil {
		users := r.Users
		usersBytes, err := users.ToJSONWithOption(ctx, opt)
		if err != nil {
			return nil, xerrors.Errorf("cannot render to JSON: %w", err)
		}
		buf = append(buf, "\"users\":"...)
		buf = append(buf, usersBytes...)
		isWritten = true
	}
	if option.IsIncludeAll {
		if isWritten {
			buf = append(buf, ',')
		}
		sub := r.Sub
		subBytes, err := sub.ToJSON(ctx)
		if err != nil {
			return nil, xerrors.Errorf("cannot render to JSON: %w", err)
		}
		buf = append(buf, "\"sub\":"...)
		buf = append(buf, subBytes...)
		isWritten = true
	} else if opt := option.IncludeOption("sub"); opt != nil {
		if isWritten {
			buf = append(buf, ',')
		}
		sub := r.Sub
		subBytes, err := sub.ToJSONWithOption(ctx, opt)
		if err != nil {
			return nil, xerrors.Errorf("cannot render to JSON: %w", err)
		}
		buf = append(buf, "\"sub\":"...)
		buf = append(buf, subBytes...)
		isWritten = true
	}
	buf = append(buf, '}')
	return buf, nil
}

func (r *UserGetter) MarshalJSON() ([]byte, error) {
	if r.renderedBytes == nil {
		return nil, xerrors.New("response object must be created by builder")
	}
	return r.renderedBytes, nil
}

type UserGetterBuilder struct {
	users *model.Users
	sub   *UserGetterSubtype
}

func (b *UserGetterBuilder) SetUsers(value *model.Users) *UserGetterBuilder {
	b.users = value
	return b
}

func (b *UserGetterBuilder) SetSub(value *UserGetterSubtype) *UserGetterBuilder {
	b.sub = value
	return b
}

func (b *UserGetterBuilder) Build(ctx context.Context) (*UserGetter, error) {
	var res UserGetter
	res.Users = b.users
	res.Sub = b.sub
	optBuilder := model.NewRenderOptionBuilder()
	optBuilder.IncludeWithCallback("users", func(optBuilder *model.RenderOptionBuilder) {
		optBuilder.Only("id", "name")
		optBuilder.IncludeWithCallback("user_fields", func(optBuilder *model.RenderOptionBuilder) {
			optBuilder.Only("field_id")
		})
	})
	optBuilder.IncludeWithCallback("sub", func(optBuilder *model.RenderOptionBuilder) {
		optBuilder.IncludeWithCallback("user", func(optBuilder *model.RenderOptionBuilder) {
			optBuilder.Only("name", "param_1", "param_2")
			optBuilder.IncludeWithCallback("user_fields", func(optBuilder *model.RenderOptionBuilder) {
				optBuilder.Only("field_id")
				optBuilder.IncludeWithCallback("field", func(optBuilder *model.RenderOptionBuilder) {
					optBuilder.Only("name")
				})
			})
		})
	})
	bytes, err := res.ToJSONWithOption(ctx, optBuilder.Build())
	if err != nil {
		return nil, xerrors.Errorf("failed to render json: %w", err)
	}
	res.renderedBytes = bytes
	return &res, nil
}
