package dbus

import (
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"
)

// Heavily inspired by the lexer from text/template.

type varToken struct {
	typ varTokenType
	val string
}

type varTokenType byte

const (
	tokEOF varTokenType = iota
	tokError
	tokNumber
	tokString
	tokBool
	tokArrayStart
	tokArrayEnd
	tokDictStart
	tokDictEnd
	tokVariantStart
	tokVariantEnd
	tokComma
	tokColon
	tokType
	tokByteString
)

type varLexer struct {
	input  string
	start  int
	pos    int
	width  int
	tokens []varToken
}

type lexState func(*varLexer) lexState

func varLex(s string) []varToken {
	l := &varLexer{input: s}
	l.run()
	return l.tokens
}

func (l *varLexer) accept(valid string) bool {
	if strings.ContainsRune(valid, l.next()) {
		return true
	}
	l.backup()
	return false
}

func (l *varLexer) backup() {
	l.pos -= l.width
}

func (l *varLexer) emit(t varTokenType) {
	l.tokens = append(l.tokens, varToken{t, l.input[l.start:l.pos]})
	l.start = l.pos
}

func (l *varLexer) errorf(format string, v ...interface{}) lexState {
	l.tokens = append(l.tokens, varToken{
		tokError,
		fmt.Sprintf(format, v...),
	})
	return nil
}

func (l *varLexer) ignore() {
	l.start = l.pos
}

func (l *varLexer) next() rune {
	var r rune

	if l.pos >= len(l.input) {
		l.width = 0
		return -1
	}
	r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
	l.pos += l.width
	return r
}

func (l *varLexer) run() {
	for state := varLexNormal; state != nil; {
		state = state(l)
	}
}

func (l *varLexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}

func varLexNormal(l *varLexer) lexState {
	for {
		r := l.next()
		switch {
		case r == -1:
			l.emit(tokEOF)
			return nil
		case r == '[':
			l.emit(tokArrayStart)
		case r == ']':
			l.emit(tokArrayEnd)
		case r == '{':
			l.emit(tokDictStart)
		case r == '}':
			l.emit(tokDictEnd)
		case r == '<':
			l.emit(tokVariantStart)
		case r == '>':
			l.emit(tokVariantEnd)
		case r == ':':
			l.emit(tokColon)
		case r == ',':
			l.emit(tokComma)
		case r == '\'' || r == '"':
			l.backup()
			return varLexString
		case r == '@':
			l.backup()
			return varLexType
		case unicode.IsSpace(r):
			l.ignore()
		case unicode.IsNumber(r) || r == '+' || r == '-':
			l.backup()
			return varLexNumber
		case r == 'b':
			pos := l.start
			if n := l.peek(); n == '"' || n == '\'' {
				return varLexByteString
			}
			// not a byte string; try to parse it as a type or bool below
			l.pos = pos + 1
			l.width = 1
			fallthrough
		default:
			// either a bool or a type. Try bools first.
			l.backup()
			if l.pos+4 <= len(l.input) {
				if l.input[l.pos:l.pos+4] == "true" {
					l.pos += 4
					l.emit(tokBool)
					continue
				}
			}
			if l.pos+5 <= len(l.input) {
				if l.input[l.pos:l.pos+5] == "false" {
					l.pos += 5
					l.emit(tokBool)
					continue
				}
			}
			// must be a type.
			return varLexType
		}
	}
}

var varTypeMap = map[string]string{
	"boolean":    "b",
	"byte":       "y",
	"int16":      "n",
	"uint16":     "q",
	"int32":      "i",
	"uint32":     "u",
	"int64":      "x",
	"uint64":     "t",
	"double":     "f",
	"string":     "s",
	"objectpath": "o",
	"signature":  "g",
}

func varLexByteString(l *varLexer) lexState {
	q := l.next()
Loop:
	for {
		switch l.next() {
		case '\\':
			if r := l.next(); r != -1 {
				break
			}
			fallthrough
		case -1:
			return l.errorf("unterminated bytestring")
		case q:
			break Loop
		}
	}
	l.emit(tokByteString)
	return varLexNormal
}

func varLexNumber(l *varLexer) lexState {
	l.accept("+-")
	digits := "0123456789"
	if l.accept("0") {
		if l.accept("x") {
			digits = "0123456789abcdefABCDEF"
		} else {
			digits = "01234567"
		}
	}
	for strings.ContainsRune(digits, l.next()) {
	}
	l.backup()
	if l.accept(".") {
		for strings.ContainsRune(digits, l.next()) {
		}
		l.backup()
	}
	if l.accept("eE") {
		l.accept("+-")
		for strings.ContainsRune("0123456789", l.next()) {
		}
		l.backup()
	}
	if r := l.peek(); unicode.IsLetter(r) {
		l.next()
		return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
	}
	l.emit(tokNumber)
	return varLexNormal
}

func varLexString(l *varLexer) lexState {
	q := l.next()
Loop:
	for {
		switch l.next() {
		case '\\':
			if r := l.next(); r != -1 {
				break
			}
			fallthrough
		case -1:
			return l.errorf("unterminated string")
		case q:
			break Loop
		}
	}
	l.emit(tokString)
	return varLexNormal
}

func varLexType(l *varLexer) lexState {
	at := l.accept("@")
	for {
		r := l.next()
		if r == -1 {
			break
		}
		if unicode.IsSpace(r) {
			l.backup()
			break
		}
	}
	if at {
		if _, err := ParseSignature(l.input[l.start+1 : l.pos]); err != nil {
			return l.errorf("%s", err)
		}
	} else {
		if _, ok := varTypeMap[l.input[l.start:l.pos]]; ok {
			l.emit(tokType)
			return varLexNormal
		}
		return l.errorf("unrecognized type %q", l.input[l.start:l.pos])
	}
	l.emit(tokType)
	return varLexNormal
}
