// Copyright 2018 The CUE Authors
//
// Licensed 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
//
//     http://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 cue

import (
	"math/big"

	"github.com/cockroachdb/apd/v2"

	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/literal"
)

func newRepresentation(m multiplier, base int, sep bool) multiplier {
	switch base {
	case 10:
		m |= base10
	case 2:
		m |= base2
	case 8:
		m |= base8
	case 16:
		m |= base16
	}
	if sep {
		m |= hasSeparators
	}
	return m
}

func (m multiplier) multiplier() multiplier { return m & (hasSeparators - 1) }

type multiplier uint16

const (
	mul1 multiplier = 1 << iota
	mul2
	mul3
	mul4
	mul5
	mul6
	mul7
	mul8

	mulBin
	mulDec

	// _ 3 for dec, 4 for hex. Maybe support first and rest, like CLDR.
	hasSeparators

	base2
	base8
	base10
	base16

	mulK = mulDec | mul1
	mulM = mulDec | mul2
	mulG = mulDec | mul3
	mulT = mulDec | mul4
	mulP = mulDec | mul5
	mulE = mulDec | mul6
	mulZ = mulDec | mul7
	mulY = mulDec | mul8

	mulKi = mulBin | mul1
	mulMi = mulBin | mul2
	mulGi = mulBin | mul3
	mulTi = mulBin | mul4
	mulPi = mulBin | mul5
	mulEi = mulBin | mul6
	mulZi = mulBin | mul7
	mulYi = mulBin | mul8
)

type litParser struct {
	ctx  *context
	node *ast.BasicLit
	src  string
	p    int
	// pDot   int // first position after the dot, if any
	ch     byte
	useSep bool
	buf    []byte
	err    value
}

func (p *litParser) error(l ast.Node, args ...interface{}) value {
	return p.ctx.mkErr(newNode(l), args...)
}

func (p *litParser) next() bool {
	if p.p >= len(p.src) {
		p.ch = 0
		return false
	}
	p.ch = p.src[p.p]
	p.p++
	if p.ch == '.' {
		if len(p.buf) == 0 {
			p.buf = append(p.buf, '0')
		}
		p.buf = append(p.buf, '.')
	}
	return true
}

func (p *litParser) init(l *ast.BasicLit) (err value) {
	s := l.Value
	b := p.buf
	*p = litParser{ctx: p.ctx, node: l, src: s}
	p.buf = b[:0]
	if !p.next() {
		return p.error(l, "invalid literal %q", s)
	}
	return nil
}

func (p *litParser) parse(l *ast.BasicLit) (n value) {
	s := l.Value
	switch s {
	case "null":
		return &nullLit{newExpr(l)}
	case "true":
		return &boolLit{newExpr(l), true}
	case "false":
		return &boolLit{newExpr(l), false}
	}
	if err := p.init(l); err != nil {
		return err
	}
	switch p.ch {
	case '"', '\'', '`', '#':
		info, nStart, _, err := literal.ParseQuotes(s, s)
		if err != nil {
			return p.error(l, err.Error())
		}
		s := p.src[nStart:]
		return parseString(p.ctx, p.node, info, s)
	case '.':
		p.next()
		n = p.scanNumber(true)
	default:
		n = p.scanNumber(false)
	}
	if p.err != nil {
		return p.err
	}
	if p.p < len(p.src) {
		return p.error(l, "invalid number")
	}
	return n
}

// parseString decodes a string without the starting and ending quotes.
func parseString(ctx *context, node ast.Expr, q literal.QuoteInfo, s string) (n value) {
	src := newExpr(node)
	str, err := q.Unquote(s)
	if err != nil {
		return ctx.mkErr(src, "invalid string: %v", err)
	}
	if q.IsDouble() {
		return &stringLit{src, str, nil}
	}
	return &bytesLit{src, []byte(str), nil}
}

func (p *litParser) digitVal(ch byte) (d int) {
	switch {
	case '0' <= ch && ch <= '9':
		d = int(ch - '0')
	case ch == '_':
		p.useSep = true
		return 0
	case 'a' <= ch && ch <= 'f':
		d = int(ch - 'a' + 10)
	case 'A' <= ch && ch <= 'F':
		d = int(ch - 'A' + 10)
	default:
		return 16 // larger than any legal digit val
	}
	return d
}

func (p *litParser) scanMantissa(base int) {
	var last byte
	for p.digitVal(p.ch) < base {
		if p.ch != '_' {
			p.buf = append(p.buf, p.ch)
		}
		last = p.ch
		p.next()
	}
	if last == '_' {
		p.err = p.error(p.node, "illegal '_' in number")
	}
}

func (p *litParser) scanNumber(seenDecimalPoint bool) value {
	isFloat := false
	base := 10

	if seenDecimalPoint {
		isFloat = true
		p.scanMantissa(10)
		goto exponent
	}

	if p.ch == '0' {
		// int or float
		p.next()
		switch p.ch {
		case 'x', 'X':
			base = 16
			// hexadecimal int
			p.next()
			p.scanMantissa(16)
			if p.p <= 2 {
				// only scanned "0x" or "0X"
				return p.error(p.node, "illegal hexadecimal number %q", p.src)
			}
		case 'b':
			base = 2
			// binary int
			p.next()
			p.scanMantissa(2)
			if p.p <= 2 {
				// only scanned "0b"
				return p.error(p.node, "illegal binary number %q", p.src)
			}
		case 'o':
			base = 8
			// octal int
			p.next()
			p.scanMantissa(8)
			if p.p <= 2 {
				// only scanned "0o"
				return p.error(p.node, "illegal octal number %q", p.src)
			}
		default:
			// int (base 8 or 10) or float
			p.scanMantissa(8)
			if p.ch == '8' || p.ch == '9' {
				p.scanMantissa(10)
				if p.ch != '.' && p.ch != 'e' && p.ch != 'E' {
					return p.error(p.node, "illegal integer number %q", p.src)
				}
			}
			switch p.ch {
			case 'e', 'E':
				if len(p.buf) == 0 {
					p.buf = append(p.buf, '0')
				}
				fallthrough
			case '.':
				goto fraction
			}
			if len(p.buf) > 0 {
				base = 8
			}
		}
		goto exit
	}

	// decimal int or float
	p.scanMantissa(10)

	// TODO: allow 3h4s, etc.
	// switch p.ch {
	// case 'h', 'm', 's', "µ"[0], 'u', 'n':
	// }

fraction:
	if p.ch == '.' {
		isFloat = true
		p.next()
		p.scanMantissa(10)
	}

exponent:
	switch p.ch {
	case 'K', 'M', 'G', 'T', 'P':
		mul := charToMul[p.ch]
		p.next()
		if p.ch == 'i' {
			mul |= mulBin
			p.next()
		} else {
			mul |= mulDec
		}
		n := newInt(newExpr(p.node), newRepresentation(mul, 10, p.useSep))
		n.v.UnmarshalText(p.buf)
		p.ctx.Mul(&n.v, &n.v, mulToRat[mul])
		cond, _ := p.ctx.RoundToIntegralExact(&n.v, &n.v)
		if cond.Inexact() {
			return p.error(p.node, "number cannot be represented as int")
		}
		return n

	case 'e', 'E':
		isFloat = true
		p.next()
		p.buf = append(p.buf, 'e')
		if p.ch == '-' || p.ch == '+' {
			p.buf = append(p.buf, p.ch)
			p.next()
		}
		p.scanMantissa(10)
	}

exit:
	if isFloat {
		f := newFloat(newExpr(p.node), newRepresentation(0, 10, p.useSep))
		f.v.UnmarshalText(p.buf)
		return f
	}
	i := newInt(newExpr(p.node), newRepresentation(0, base, p.useSep))
	i.v.Coeff.SetString(string(p.buf), base)
	return i
}

type mulInfo struct {
	fact *big.Rat
	mul  multiplier
}

var charToMul = map[byte]multiplier{
	'K': mul1,
	'M': mul2,
	'G': mul3,
	'T': mul4,
	'P': mul5,
	'E': mul6,
	'Z': mul7,
	'Y': mul8,
}

var mulToRat = map[multiplier]*apd.Decimal{}

func init() {
	d := apd.New(1, 0)
	b := apd.New(1, 0)
	dm := apd.New(1000, 0)
	bm := apd.New(1024, 0)

	c := apd.BaseContext
	for i := uint(0); int(i) < len(charToMul); i++ {
		// TODO: may we write to one of the sources?
		var bn, dn apd.Decimal
		c.Mul(&dn, d, dm)
		d = &dn
		c.Mul(&bn, b, bm)
		b = &bn
		mulToRat[mulDec|1<<i] = d
		mulToRat[mulBin|1<<i] = b
	}
}
