package jsonvalue

import (
	"io"
)

const (
	initialArrayCapacity = 32
	asciiSize            = 128
)

// Deprecated: Opt is the option of jsonvalue in marshaling. This type is deprecated,
// please use OptXxxx() functions instead.
//
// Opt 表示序列化当前 jsonvalue 类型时的参数。这个类型后续可能不再迭代新字段了，请改用 OptXxxx() 函数进行配置。
type Opt struct {
	// OmitNull tells how to handle null json value. The default value is false.
	// If OmitNull is true, null value will be omitted when marshaling.
	//
	// OmitNull 表示是否忽略 JSON 中的 null 类型值。默认为 false.
	OmitNull bool

	// ignoreJsonOmitempty ignore json tag "omitempty", which means that every data
	// would be parsed into *jsonvalue.V
	ignoreJsonOmitempty bool

	// MarshalLessFunc is used to handle sequences of marshaling. Since object is
	// implemented by hash map, the sequence of keys is unexpectable. For situations
	// those need settled JSON key-value sequence, please use MarshalLessFunc.
	//
	// Note: Elements in an array value would NOT trigger this function as they are
	// already sorted.
	//
	// We provides a example DefaultStringSequence. It is quite useful when calculating
	// idempotence of a JSON text, as key-value sequences should be fixed.
	//
	// MarshalLessFunc 用于处理序列化 JSON 对象类型时，键值对的顺序。由于 object 类型是采用 go
	// 原生的 map 类型，采用哈希算法实现，
	// 因此其键值对的顺序是不可控的。而为了提高效率，jsonvalue 的内部实现中并不会刻意保存键值对的顺序。
	// 如果有必要在序列化时固定键值对顺序的话，
	// 可以使用这个函数。
	//
	// 注意：array 类型中键值对的顺序不受这个函数的影响
	//
	// 此外，我们提供了一个例子: DefaultStringSequence。当需要计算 JSON 文本的幂等值时，
	// 由于需要不变的键值对顺序，因此这个函数是非常有用的。
	MarshalLessFunc MarshalLessFunc

	// MarshalKeySequence is used to handle sequance of marshaling. This is much simpler
	// than MarshalLessFunc, just pass a string slice identifying key sequence. For keys
	// those are not in this slice, they would be appended in the end according to result
	// of Go string comparing. Therefore this parameter is useful for ensure idempotence.
	//
	// MarshalKeySequence 也用于处理序列化时的键值对顺序。与 MarshalLessFunc 不同，这个只需要用字符串
	// 切片的形式指定键的顺序即可，实现上更为简易和直观。对于那些不在指定切片中的键，那么将会统一放在结尾，
	// 并且按照 go 字符串对比的结果排序。也可以保证幂等。
	MarshalKeySequence []string
	keySequence        map[string]int // generated from MarshalKeySequence

	// marshalBySetSequence enables object key sequence by when it is set.
	//
	// 按照 key 被设置的顺序处理序列化时的 marshal 顺序
	marshalBySetSequence bool

	// FloatNaNHandleType tells what to deal with float NaN.
	//
	// FloatNaNHandleType 表示当处理 float 的时候，如果遇到了 NaN 的话，要如何处理。
	FloatNaNHandleType FloatNaNHandleType
	// FloatNaNToString works with FloatNaNHandleType = FloatNaNConvertToString. It tells
	// what string to replace to with NaN. If not specified, NaN will be set as string "NaN".
	//
	// FloatNaNToString 搭配 FloatNaNHandleType = FloatNaNConvertToString 使用，表示将 NaN
	// 映射为哪个字符串。这个值如果不指定，则默认会被设置为字符串 "NaN"
	FloatNaNToString string
	// FloatNaNToFloat works with FloatNaNHandleType = FloatNaNConvertToFloat. It tells
	// what float number will be mapped to as for NaN. NaN, +Inf or -Inf are not allowed
	// for this option.
	//
	// FloatNaNToFloat 搭配 FloatNaNHandleType = FloatNaNConvertToFloat 使用，表示将 NaN
	// 映射为哪个 float64 值。不允许指定为 NaN, +Inf 或 -Inf。如果不指定，则映射为 0。
	FloatNaNToFloat float64

	// FloatInfHandleType tells what to deal with float +Inf and -Inf.
	//
	// FloatInfHandleType 表示当处理 float 的时候，如果遇到了 +Inf 和 -Inf 的话，要如何处理。
	FloatInfHandleType FloatInfHandleType
	// FloatInfPositiveToString works with FloatInfHandleType = FloatInfConvertToFloat.
	// It tells what float number will be mapped to as for +Inf. If not specified, +Inf
	// will be set as string "+Inf".
	//
	// FloatInfPositiveToString 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用,
	// 表示将 NaN 映射为哪个字符串。
	// 这个值如果不指定，则默认会被设置为字符串 "+Inf"
	FloatInfPositiveToString string
	// FloatInfNegativeToString works with FloatInfHandleType = FloatInfConvertToFloat.
	// It tells what float number will be mapped to as for -Inf. If not specified, -Inf
	// will be set as string "-" + strings.TrimLeft(FloatInfPositiveToString, "+").
	//
	// FloatInfNegativeToString 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用,
	// 表示将 NaN 映射为哪个字符串。这个值如果不指定，则默认会被设置为字符串 "-" + strings.TrimLeft(FloatInfPositiveToString, "+")
	FloatInfNegativeToString string
	// FloatInfToFloat works with FloatInfHandleType = FloatInfConvertToFloat. It tells
	// what float numbers will be mapped to as for +Inf. And -Inf will be specified as
	// the negative value of this option. +Inf or -Inf are not allowed for this option.
	//
	// FloatInfToFloat 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用，表示将 +Inf
	// 映射为哪个 float64 值。而 -Inf 则会被映射为这个值的负数。不允许指定为 NaN, +Inf 或 -Inf。
	// 如果不指定，则映射为 0
	FloatInfToFloat float64

	// unicodeEscapingFunc defines how to escaping a unicode greater than 0x7F to buffer.
	unicodeEscapingFunc func(r rune, buf io.Writer)

	// asciiCharEscapingFunc defines how to marshal bytes lower than 0x80.
	asciiCharEscapingFunc [asciiSize]func(b byte, buf io.Writer)

	// escProperties
	escProperties escapingProperties

	// indent
	indent struct {
		enabled bool
		prefix  string
		indent  string
		cnt     int
	}
}

type FloatNaNHandleType uint8

const (
	// FloatNaNTreatAsError indicates that error will be returned when a float number
	// is NaN when marshaling.
	//
	// FloatNaNTreatAsError 表示当 marshal 遇到 NaN 时，返回错误。这是默认选项。
	FloatNaNTreatAsError FloatNaNHandleType = 0
	// FloatNaNConvertToFloat indicates that NaN will be replaced as another float
	// number when marshaling. This option works with option FloatNaNToFloat.
	//
	// FloatNaNConvertToFloat 表示当 marshal 遇到 NaN 时，将值置为另一个数。搭配 FloatNaNToFloat
	// 选项使用。
	FloatNaNConvertToFloat FloatNaNHandleType = 1
	// FloatNaNNull indicates that NaN key-value pair will be set as null when marshaling.
	//
	// FloatNaNNull 表示当 marshal 遇到 NaN 时，则将值设置为 null
	FloatNaNNull FloatNaNHandleType = 2
	// FloatNaNConvertToString indicates that NaN will be replaced as a string when
	//  marshaling. This option works with option FloatNaNToString.
	//
	// FloatNaNConvertToString 表示当 marshal 遇到 NaN 时，将值设置为一个字符串。搭配
	// FloatNaNToString 选项使用。
	FloatNaNConvertToString FloatNaNHandleType = 3
)

type FloatInfHandleType uint8

const (
	// FloatInfTreatAsError indicates that error will be returned when a float number
	// is Inf or -Inf when marshaling.
	//
	// FloatInfTreatAsError 表示当 marshal 遇到 Inf 或 -Inf 时，返回错误。这是默认选项。
	FloatInfTreatAsError FloatInfHandleType = 0
	// FloatInfConvertToFloat indicates that Inf and -Inf will be replaced as another
	// float number when marshaling. This option works with option FloatInfToFloat.
	//
	// FloatInfConvertToFloat 表示当 marshal 遇到 Inf 或 -Inf 时，将值置为另一个数。搭配
	// FloatInfToFloat 选项使用。
	FloatInfConvertToFloat FloatInfHandleType = 1
	// FloatInfNull indicates that Inf or -Inf key-value pair will be set as null
	// when marshaling.
	//
	// FloatInfNull 表示当 marshal 遇到 Inf 和 -Inf 时，则将值设置为 null
	FloatInfNull FloatInfHandleType = 2
	// FloatInfConvertToString indicates that Inf anf -Inf will be replaced as a
	// string when marshaling. This option works with option FloatInfPositiveToString
	// and FloatInfNegativeToString.
	//
	// FloatInfConvertToString 表示当 marshal 遇到 Inf 和 -Inf 时，将值设置为一个字符串。
	// 搭配 FloatInfPositiveToString FloatInfNegativeToString 选项使用。
	FloatInfConvertToString FloatInfHandleType = 3
)

// Option is used for additional options when marshaling. Can be either a Opt{}
// (not pointer to it) or other options generated by jsonvalue.OptXxxx() functions.
//
// Option 表示用于序列化的额外选项。可以是一个 Opt{} 结构体值（而不是它的指针），或者是使用
// jsonvalue.OptXxxx() 函数生成的选项。
type Option interface {
	mergeTo(*Opt)
}

func (o Opt) mergeTo(tgt *Opt) {
	*tgt = o
}

// SetDefaultMarshalOptions set default option for marshaling. It is quite
// useful to invoke this function once in certern init funciton. Or you can
// invoke it after main entry. It is goroutine-safe.
//
// Please keep in mind that it takes effect globally and affects ALL marshaling
// behaviors in the future until the process ends. Please ensure that these
// options are acceptable for ALL future marshaling.
//
// However, you can still add additional options in later marshaling.
//
// SetDefaultMarshalOptions 设置序列化时的默认参数。使用方可以在 init 函数阶段，或者是
// main 函数启动后立刻调用该函数，以调整序列化时的默认行为。这个函数是协程安全的。
//
// 请记住，这个函数影响的是后续所有的序列化行为，请确保这个配置对后续的其他操作是可行的。
//
// 当然，你也可以在后续的操作中，基于原先配置的默认选项基础上，添加其他附加选项。
func SetDefaultMarshalOptions(opts ...Option) {
	opt := emptyOptions()
	opt.combineOptionsFrom(opts)
	internal.defaultMarshalOption = opt
}

// ResetDefaultMarshalOptions reset default marshaling options to system default.
//
// ResetDefaultMarshalOptions 重设序列化时的默认选项为系统最原始的版本。
func ResetDefaultMarshalOptions() {
	internal.defaultMarshalOption = emptyOptions()
}

func emptyOptions() *Opt {
	return &Opt{}
}

func getDefaultOptions() *Opt {
	res := *internal.defaultMarshalOption
	return &res
}

func combineOptions(opts []Option) *Opt {
	opt := getDefaultOptions()
	opt.combineOptionsFrom(opts)
	return opt
}

func (opt *Opt) combineOptionsFrom(opts []Option) {
	for _, o := range opts {
		o.mergeTo(opt)
	}
	opt.parseEscapingFuncs()
}

// ==== OmitNull ====

// OptOmitNull configures OmitNull field in Opt{}, identifying whether null values
// should be omitted when marshaling.
//
// OptOmitNull 配置 Opt{} 中的 OmitNull 字段，表示是否忽略 null 值。
func OptOmitNull(b bool) Option {
	return &optOmitNull{b: b}
}

type optOmitNull struct {
	b bool
}

func (o *optOmitNull) mergeTo(opt *Opt) {
	opt.OmitNull = o.b
}

// ==== IgnoreOmitempty ====

// OptIgnoreOmitempty is used in Import() and New() function. This option tells
// jsonvalue to ignore json tag "omitempty", which means that every field would
// be parsed into *jsonvalue.V.
//
// OptIgnoreOmitempty 用在 Import 和 New() 函数中。这个选项将会忽略 json 标签中的
// "omitempty" 参数。换句话说, 所有的字段都会被解析并包装到 *jsonvalue.V 值中。
func OptIgnoreOmitempty() Option {
	return optIgnoreOmitempty{}
}

type optIgnoreOmitempty struct{}

func (optIgnoreOmitempty) mergeTo(opt *Opt) {
	opt.ignoreJsonOmitempty = true
}

// ==== MarshalLessFunc ===

// OptKeySequenceWithLessFunc configures MarshalLessFunc field in Opt{}, which defines
// key sequence when marshaling.
//
// OptKeySequenceWithLessFunc 配置 Opt{} 中的 MarshalLessFunc 字段，配置序列化时的键顺序。
func OptKeySequenceWithLessFunc(f MarshalLessFunc) Option {
	return &optMarshalLessFunc{f: f}
}

// OptDefaultStringSequence configures MarshalLessFunc field in Opt{} as jsonvalue.DefaultStringSequence,
// which is dictionary sequence.
//
// OptDefaultStringSequence 配置 Opt{} 中的 MarshalLessFunc 字段为 jsonvalue.DefaultStringSequence，也就是字典序。
func OptDefaultStringSequence() Option {
	return &optMarshalLessFunc{f: DefaultStringSequence}
}

type optMarshalLessFunc struct {
	f MarshalLessFunc
}

func (o *optMarshalLessFunc) mergeTo(opt *Opt) {
	if o.f != nil {
		opt.MarshalLessFunc = o.f
		opt.MarshalKeySequence = nil
		opt.keySequence = nil
		opt.marshalBySetSequence = false
	}
}

// ==== MarshalKeySequence ====

// OptKeySequence configures MarshalKeySequence field in Opt{}.
//
// OptKeySequence 配置 Opt{} 中的 MarshalKeySequence 字段。
func OptKeySequence(seq []string) Option {
	return &optMarshalKeySequence{seq: seq}
}

type optMarshalKeySequence struct {
	seq []string
}

func (o *optMarshalKeySequence) mergeTo(opt *Opt) {
	opt.MarshalLessFunc = nil
	opt.MarshalKeySequence = o.seq
	opt.keySequence = nil
	opt.marshalBySetSequence = false
}

// ==== marshalBySetSequence ====

// OptSetSequence tells that when marshaling an object, the key will be sorted by
// the time they are added into or refreshed in its parent object. The later a key
//
//	is set or updated, the later it and its value will be marshaled.
//
// OptSetSequence 指定在序列化 object 时，按照一个 key 被设置时的顺序进行序列化。如果一个
// key 越晚添加到 object 类型，则在序列化的时候越靠后。
func OptSetSequence() Option {
	return optSetSequence{}
}

type optSetSequence struct{}

func (optSetSequence) mergeTo(opt *Opt) {
	opt.MarshalLessFunc = nil
	opt.MarshalKeySequence = nil
	opt.keySequence = nil
	opt.marshalBySetSequence = true
}

// ==== FloatNaNConvertToFloat ====

// OptFloatNaNToFloat tells that when marshaling float NaN, replace it as another
// valid float number.
//
// OptFloatNaNToFloat 指定当遇到 NaN 时，将值替换成一个有效的 float 值。
func OptFloatNaNToFloat(f float64) Option {
	return &optFloatNaNConvertToFloat{f: f}
}

type optFloatNaNConvertToFloat struct {
	f float64
}

func (o *optFloatNaNConvertToFloat) mergeTo(opt *Opt) {
	opt.FloatNaNHandleType = FloatNaNConvertToFloat
	opt.FloatNaNToFloat = o.f
}

// ==== FloatNaNNull ====

// OptFloatNaNToNull will replace a float value to null if it is NaN.
//
// OptFloatNaNToNull 表示当遇到 NaN 时，将值替换成 null
func OptFloatNaNToNull() Option {
	return optFloatNaNNull{}
}

type optFloatNaNNull struct{}

func (optFloatNaNNull) mergeTo(opt *Opt) {
	opt.FloatNaNHandleType = FloatNaNNull
}

// ==== FloatNaNConvertToString ====

// OptFloatNaNToStringNaN will replace a float value to string "NaN" if it is NaN.
//
// OptFloatNaNToStringNaN 表示遇到 NaN 时，将其替换成字符串 "NaN"
func OptFloatNaNToStringNaN() Option {
	return &optFloatNaNConvertToString{s: "NaN"}
}

// OptFloatNaNToString will replace a float value to specified string if it is NaN.
// If empty string is given, will replace as "NaN".
//
// OptFloatNaNToString 表示当遇到 NaN 时，将其替换成指定的字符串。如果指定空字符串，则替换成 "NaN"
func OptFloatNaNToString(s string) Option {
	return &optFloatNaNConvertToString{s: s}
}

type optFloatNaNConvertToString struct {
	s string
}

func (o *optFloatNaNConvertToString) mergeTo(opt *Opt) {
	opt.FloatNaNHandleType = FloatNaNConvertToString
	opt.FloatNaNToString = o.s
}

// ==== FloatInfConvertToFloat ====

// OptFloatInfToFloat will replace a +Inf float value to specified f, while -f if
// the value is -Inf.
//
// OptFloatInfToFloat 表示当遇到 +Inf 时，将其替换成另一个 float 值；如果是 -Inf，则会替换成其取负数。
func OptFloatInfToFloat(f float64) Option {
	return &optFloatInfConvertToFloat{f: f}
}

type optFloatInfConvertToFloat struct {
	f float64
}

func (o *optFloatInfConvertToFloat) mergeTo(opt *Opt) {
	opt.FloatInfHandleType = FloatInfConvertToFloat
	opt.FloatInfToFloat = o.f
}

// ==== FloatInfNull ====

// OptFloatInfToNull will replace a float value to null if it is +/-Inf.
//
// OptFloatInfToNull 表示当遇到 +/-Inf 时，将值替换成 null
func OptFloatInfToNull() Option {
	return optFloatInfNull{}
}

type optFloatInfNull struct{}

func (optFloatInfNull) mergeTo(opt *Opt) {
	opt.FloatInfHandleType = FloatInfNull
}

// ==== FloatInfConvertToString ====

// OptFloatInfToStringInf will replace a +Inf value to string "+Inf", while -Inf to "-Inf"
//
// OptFloatInfToStringInf 表示遇到 +/-Inf 时，相应地将其替换成字符串 "+Inf" 和 "-Inf"
func OptFloatInfToStringInf() Option {
	return &optFloatInfConvertToString{}
}

// OptFloatInfToString tells what string to replace when marshaling +Inf and -Inf numbers.
//
// OptFloatInfToString 表示遇到 +/-Inf 时，将其替换成什么字符串。
func OptFloatInfToString(positiveInf, negativeInf string) Option {
	return &optFloatInfConvertToString{
		positive: positiveInf,
		negative: negativeInf,
	}
}

type optFloatInfConvertToString struct {
	positive string
	negative string
}

func (o *optFloatInfConvertToString) mergeTo(opt *Opt) {
	opt.FloatInfHandleType = FloatInfConvertToString
	opt.FloatInfPositiveToString = o.positive
	opt.FloatInfNegativeToString = o.negative
}

// ==== escapeHTML ====

// OptEscapeHTML specifies whether problematic HTML characters should be escaped
// inside JSON quoted strings. The default behavior is to escape &, <, and > to
// \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when
// embedding JSON in HTML. If not specified, HTML symbols above will be escaped by
// default.
//
// OptEscapeHTML 指定部分 HTML 符号是否会被转义。相关的 HTML 符号为 &, <, > 三个。如无指定,
// 则默认会被转义
func OptEscapeHTML(on bool) Option {
	return optEscapeHTML(on)
}

type optEscapeHTML bool

func (o optEscapeHTML) mergeTo(opt *Opt) {
	if o {
		opt.escProperties = opt.escProperties.clear(escapeWithoutHTML)
	} else {
		opt.escProperties = opt.escProperties.set(escapeWithoutHTML)
	}
}

// ==== do or do not not use ASCII escaping ====

// OptUTF8 specifies that all unicodes greater than 0x7F, will NOT be escaped by
// \uXXXX format but UTF-8.
//
// OptUTF8 指定使用 UTF-8 编码。也就是说针对大于 0x7F 的 unicode 字符，将不会使用默认的 \uXXXX
// 格式进行编码，而是直接使用 UTF-8。
func OptUTF8() Option {
	return optUTF8(true)
}

type optUTF8 bool

func (o optUTF8) mergeTo(opt *Opt) {
	opt.escProperties = opt.escProperties.set(escapeUTF8)
}

// ==== ignore slash ====

// OptEscapeSlash specifies whether we should escape slash (/) symbol. In JSON standard,
// this character should be escaped as '\/'. But non-escaping will not affect anything.
// If not specfied, slash will be escaped by default.
//
//	OptEscapeSlash 指定是否需要转移斜杠 (/) 符号。在 JSON 标准中这个符号是需要被转移为 '\/' 的,
//
// 但是不转义这个符号也不会带来什么问题。如无明确指定，如无指定，默认情况下，斜杠是会被转义的。
func OptEscapeSlash(on bool) Option {
	return optEscSlash(on)
}

type optEscSlash bool

func (o optEscSlash) mergeTo(opt *Opt) {
	if o {
		opt.escProperties = opt.escProperties.clear(escapeIgnoreSlash)
	} else {
		opt.escProperties = opt.escProperties.set(escapeIgnoreSlash)
	}
}

// escapingProperties is a bit mask, showing the option for escaping
// characters.
//
// escapingProperties 是一个位掩码，表明转义特殊字符的方法
type escapingProperties uint8

const (
	escapeUTF8        = 0
	escapeWithoutHTML = 1
	escapeIgnoreSlash = 2
)

func (esc escapingProperties) set(mask escapingProperties) escapingProperties {
	return esc | (1 << mask)
}

func (esc escapingProperties) clear(mask escapingProperties) escapingProperties {
	return esc & ^(1 << mask)
}

func (esc escapingProperties) has(mask escapingProperties) bool {
	return esc == esc.set(mask)
}

// parseEscapingFuncs parse escaping functions by escapingProperties.
func (o *Opt) parseEscapingFuncs() {
	// init bytes lower than 0x80
	for i := range o.asciiCharEscapingFunc {
		o.asciiCharEscapingFunc[i] = escapeNothing
	}

	iterate := func(from, to int, fu func(b byte, buf io.Writer)) {
		for i := from; i <= to; i++ {
			o.asciiCharEscapingFunc[i] = fu
		}
	}

	// ASCII control bytes should always escaped
	iterate(0x00, 0x07, escAsciiControlChar)
	// 0x08 is \b, encoding/json marshal as \u0008, but according to JSON standard, it should be "\b"
	iterate(0x0E, 0x1F, escAsciiControlChar)
	o.asciiCharEscapingFunc[0x7F] = escAsciiControlChar // encoding/json does not escape DEL

	// ASCII characters always to be escaped
	o.asciiCharEscapingFunc['"'] = escDoubleQuote
	o.asciiCharEscapingFunc['/'] = escSlash
	o.asciiCharEscapingFunc['\\'] = escBackslash
	o.asciiCharEscapingFunc['\b'] = escBackspace
	o.asciiCharEscapingFunc['\f'] = escVertTab
	o.asciiCharEscapingFunc['\t'] = escTab
	o.asciiCharEscapingFunc['\n'] = escNewLine
	o.asciiCharEscapingFunc['\r'] = escReturn
	o.asciiCharEscapingFunc['<'] = escLeftAngle
	o.asciiCharEscapingFunc['>'] = escRightAngle
	o.asciiCharEscapingFunc['&'] = escAnd
	// o.asciiCharEscapingFunc['%'] = escPercent

	// unicodes >= 0x80
	if o.escProperties.has(escapeUTF8) {
		o.unicodeEscapingFunc = escapeGreaterUnicodeToBuffByUTF8
	} else {
		o.unicodeEscapingFunc = escapeGreaterUnicodeToBuffByUTF16
	}

	// ignore slash?
	if o.escProperties.has(escapeIgnoreSlash) {
		o.asciiCharEscapingFunc['/'] = escapeNothing
	}

	// without HTML?
	if o.escProperties.has(escapeWithoutHTML) {
		o.asciiCharEscapingFunc['<'] = escapeNothing
		o.asciiCharEscapingFunc['>'] = escapeNothing
		o.asciiCharEscapingFunc['&'] = escapeNothing
	}
}

// ==== indent ====

// OptIndent appliesiIndent to format the output.
//
// OptIndent 指定序列化时的缩进。
func OptIndent(prefix, indent string) Option {
	return optionIndent{prefix, indent}
}

type optionIndent [2]string

func (o optionIndent) mergeTo(opt *Opt) {
	opt.indent.enabled = true
	opt.indent.prefix = o[0]
	opt.indent.indent = o[1]
}
