// Copyright 2021 Google LLC
//
// 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 parser

import (
	antlr "github.com/antlr4-go/antlr/v4"

	"cel.dev/cel-go/common/runes"
)

type charStream struct {
	buf runes.Buffer
	pos int
	src string
}

// Consume implements (antlr.CharStream).Consume.
func (c *charStream) Consume() {
	if c.pos >= c.buf.Len() {
		panic("cannot consume EOF")
	}
	c.pos++
}

// LA implements (antlr.CharStream).LA.
func (c *charStream) LA(offset int) int {
	if offset == 0 {
		return 0
	}
	if offset < 0 {
		offset++
	}
	pos := c.pos + offset - 1
	if pos < 0 || pos >= c.buf.Len() {
		return antlr.TokenEOF
	}
	return int(c.buf.Get(pos))
}

// LT mimics (*antlr.InputStream).LT.
func (c *charStream) LT(offset int) int {
	return c.LA(offset)
}

// Mark implements (antlr.CharStream).Mark.
func (c *charStream) Mark() int {
	return -1
}

// Release implements (antlr.CharStream).Release.
func (c *charStream) Release(marker int) {}

// Index implements (antlr.CharStream).Index.
func (c *charStream) Index() int {
	return c.pos
}

// Seek implements (antlr.CharStream).Seek.
func (c *charStream) Seek(index int) {
	if index <= c.pos {
		c.pos = index
		return
	}
	if index < c.buf.Len() {
		c.pos = index
	} else {
		c.pos = c.buf.Len()
	}
}

// Size implements (antlr.CharStream).Size.
func (c *charStream) Size() int {
	return c.buf.Len()
}

// GetSourceName implements (antlr.CharStream).GetSourceName.
func (c *charStream) GetSourceName() string {
	return c.src
}

// GetText implements (antlr.CharStream).GetText.
func (c *charStream) GetText(start, stop int) string {
	if stop >= c.buf.Len() {
		stop = c.buf.Len() - 1
	}
	if start >= c.buf.Len() {
		return ""
	}
	return c.buf.Slice(start, stop+1)
}

// GetTextFromTokens implements (antlr.CharStream).GetTextFromTokens.
func (c *charStream) GetTextFromTokens(start, stop antlr.Token) string {
	if start != nil && stop != nil {
		return c.GetText(start.GetTokenIndex(), stop.GetTokenIndex())
	}
	return ""
}

// GetTextFromInterval implements (antlr.CharStream).GetTextFromInterval.
func (c *charStream) GetTextFromInterval(i antlr.Interval) string {
	return c.GetText(i.Start, i.Stop)
}

// String mimics (*antlr.InputStream).String.
func (c *charStream) String() string {
	return c.buf.Slice(0, c.buf.Len())
}

var _ antlr.CharStream = &charStream{}

func newCharStream(buf runes.Buffer, desc string) antlr.CharStream {
	return &charStream{
		buf: buf,
		src: desc,
	}
}
