/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package utils

import (
	"context"
	"encoding/binary"
	"encoding/xml"
	"fmt"
	"math/big"
	"strings"
	"unicode"
)

type WriteBufferXmlBased interface {
	WriteBuffer
	GetXmlString() string
}

// NewXmlWriteBuffer returns a WriteBufferXmlBased which renders all information into xml
func NewXmlWriteBuffer() WriteBufferXmlBased {
	var xmlString strings.Builder
	encoder := xml.NewEncoder(&xmlString)
	encoder.Indent("", "  ")
	return &xmlWriteBuffer{
		xmlString:     &xmlString,
		Encoder:       encoder,
		doRenderLists: true,
		doRenderAttr:  true,
	}
}

// NewConfiguredXmlWriteBuffer returns a WriteBufferXmlBased which renders configured information into xml
func NewConfiguredXmlWriteBuffer(renderLists bool, renderAttr bool) WriteBufferXmlBased {
	var xmlString strings.Builder
	encoder := xml.NewEncoder(&xmlString)
	encoder.Indent("", "  ")
	return &xmlWriteBuffer{
		xmlString:     &xmlString,
		Encoder:       encoder,
		doRenderLists: renderLists,
		doRenderAttr:  renderAttr,
	}
}

///////////////////////////////////////
///////////////////////////////////////
//
// Internal section
//

type xmlWriteBuffer struct {
	BufferCommons
	xmlString *strings.Builder
	*xml.Encoder
	doRenderLists bool
	doRenderAttr  bool
	pos           uint
}

var _ WriteBuffer = (*xmlWriteBuffer)(nil)

//
// Internal section
//
///////////////////////////////////////
///////////////////////////////////////

func (*xmlWriteBuffer) GetByteOrder() binary.ByteOrder {
	return binary.BigEndian
}

func (*xmlWriteBuffer) SetByteOrder(_ binary.ByteOrder) {
}

func (x *xmlWriteBuffer) PushContext(logicalName string, writerArgs ...WithWriterArgs) error {
	// Pre-emptive flush to avoid overflow when for a long time no context gets popped
	if err := x.Flush(); err != nil {
		return err
	}
	attrs := make([]xml.Attr, 0)
	attrs = x.markAsListIfRequired(writerArgs, attrs)
	return x.EncodeToken(xml.StartElement{Name: xml.Name{Local: x.SanitizeLogicalName(logicalName)}, Attr: attrs})
}

func (x *xmlWriteBuffer) GetPos() uint16 {
	return uint16(x.pos * 8)
}

func (x *xmlWriteBuffer) WriteBit(logicalName string, value bool, writerArgs ...WithWriterArgs) error {
	x.move(1)
	return x.encodeElement(logicalName, value, x.generateAttr(rwBitKey, 1, writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteByte(logicalName string, value byte, writerArgs ...WithWriterArgs) error {
	x.move(8)
	return x.encodeElement(logicalName, fmt.Sprintf("%#02x", value), x.generateAttr(rwByteKey, 8, writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteByteArray(logicalName string, data []byte, writerArgs ...WithWriterArgs) error {
	hexString := fmt.Sprintf("%#02x", data)
	if hexString == "00" {
		// golang does mess up the formatting on empty arrays
		hexString = "0x"
	}
	x.move(uint(len(data) * 8))
	return x.encodeElement(logicalName, hexString, x.generateAttr(rwByteKey, uint(len(data)*8), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteUint8(logicalName string, bitLength uint8, value uint8, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwUintKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteUint16(logicalName string, bitLength uint8, value uint16, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwUintKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteUint32(logicalName string, bitLength uint8, value uint32, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwUintKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteUint64(logicalName string, bitLength uint8, value uint64, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwUintKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteInt8(logicalName string, bitLength uint8, value int8, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteInt16(logicalName string, bitLength uint8, value int16, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteInt32(logicalName string, bitLength uint8, value int32, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteInt64(logicalName string, bitLength uint8, value int64, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteBigInt(logicalName string, bitLength uint8, value *big.Int, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteFloat32(logicalName string, bitLength uint8, value float32, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, fmt.Sprintf("%16.16f", value), x.generateAttr(rwFloatKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteFloat64(logicalName string, bitLength uint8, value float64, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, fmt.Sprintf("%32.32f", value), x.generateAttr(rwFloatKey, uint(bitLength), writerArgs...), writerArgs...)
}

func (x *xmlWriteBuffer) WriteBigFloat(logicalName string, bitLength uint8, value *big.Float, writerArgs ...WithWriterArgs) error {
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, value, x.generateAttr(rwFloatKey, uint(bitLength), writerArgs...), writerArgs...)
}

// [^\u0009\r\n\u0020-\uD7FF\uE000-\uFFFD\ud800\udc00-\udbff\udfff]
var printableRange = &unicode.RangeTable{
	R16: []unicode.Range16{
		{0x0009, 0x0009, 1},
		{0x000D, 0x000D, 1},
		{0x000A, 0x000A, 1},
		{0x0020, 0xD7FF, 1},
		{0xE000, 0xFFFD, 1},
		{0xD800, 0xD800, 1},
		{0xDC00, 0xDBFF, 1},
		{0xDFFF, 0xDFFF, 1},
	},
}

func (x *xmlWriteBuffer) WriteString(logicalName string, bitLength uint32, value string, writerArgs ...WithWriterArgs) error {
	attr := x.generateAttr(rwStringKey, uint(bitLength), writerArgs...)
	attr = append(attr, xml.Attr{Name: xml.Name{Local: rwEncodingKey}, Value: x.ExtractEncoding(UpcastWriterArgs(writerArgs...)...)})
	cleanedUpString := strings.TrimFunc(value, func(r rune) bool {
		return !unicode.In(r, printableRange)
	})
	x.move(uint(bitLength))
	return x.encodeElement(logicalName, cleanedUpString, attr, writerArgs...)
}

func (x *xmlWriteBuffer) WriteVirtual(_ context.Context, _ string, _ any, _ ...WithWriterArgs) error {
	// NO-OP
	return nil
}

func (x *xmlWriteBuffer) WriteSerializable(ctx context.Context, serializable Serializable) error {
	if serializable == nil {
		return nil
	}
	return serializable.SerializeWithWriteBuffer(ctx, x)
}

func (x *xmlWriteBuffer) PopContext(logicalName string, _ ...WithWriterArgs) error {
	if err := x.Encoder.EncodeToken(xml.EndElement{Name: xml.Name{Local: x.SanitizeLogicalName(logicalName)}}); err != nil {
		return err
	}
	return x.Encoder.Flush()
}

func (x *xmlWriteBuffer) GetXmlString() string {
	return x.xmlString.String()
}

func (x *xmlWriteBuffer) encodeElement(logicalName string, value any, attr []xml.Attr, _ ...WithWriterArgs) error {
	return x.EncodeElement(value, xml.StartElement{
		Name: xml.Name{Local: x.SanitizeLogicalName(logicalName)},
		Attr: attr,
	})
}

func (x *xmlWriteBuffer) generateAttr(dataType string, bitLength uint, writerArgs ...WithWriterArgs) []xml.Attr {
	attrs := make([]xml.Attr, 2)
	if !x.doRenderAttr {
		return attrs
	}
	attrs[0] = xml.Attr{
		Name:  xml.Name{Local: rwDataTypeKey},
		Value: dataType,
	}
	attrs[1] = xml.Attr{
		Name:  xml.Name{Local: rwBitLengthKey},
		Value: fmt.Sprintf("%d", bitLength),
	}
	for _, arg := range writerArgs {
		if !arg.isWriterArgs() {
			panic("not a writer arg")
		}
		switch arg.(type) {
		case withAdditionalStringRepresentation:
			attrs = append(attrs, xml.Attr{
				Name:  xml.Name{Local: rwStringRepresentationKey},
				Value: arg.(withAdditionalStringRepresentation).stringRepresentation,
			})
		}
	}
	return attrs
}

func (x *xmlWriteBuffer) markAsListIfRequired(writerArgs []WithWriterArgs, attrs []xml.Attr) []xml.Attr {
	if !x.doRenderLists {
		return attrs
	}
	if x.IsToBeRenderedAsList(UpcastWriterArgs(writerArgs...)...) {
		attrs = append(attrs, xml.Attr{
			Name:  xml.Name{Local: rwIsListKey},
			Value: "true",
		})
	}
	return attrs
}

func (x *xmlWriteBuffer) move(bits uint) {
	x.pos += bits
}
