// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package reader provides an object that reads queries from various input
// sources (e.g. stdin, pipe).
package reader

import (
	"bufio"
	"os"
	"strings"
	"text/scanner"

	"github.com/peterh/liner"
)

type T struct {
	s      scanner.Scanner
	prompt prompter
}

func newT(prompt prompter) *T {
	t := &T{prompt: prompt}
	t.initScanner("")
	return t
}

// Close frees any resources acquired by this reader.
func (t *T) Close() {
	t.prompt.Close()
}

func (t *T) initScanner(input string) {
	t.s.Init(strings.NewReader(input))
	// Keep all whitespace.
	t.s.Whitespace = 0
}

// GetQuery returns an entire query where queries are delimited by semicolons.
// GetQuery returns the error io.EOF when there is no more input.
func (t *T) GetQuery() (string, error) {
	return t.GetQueryWithTerminator(';')
}

func (t *T) GetQueryWithTerminator(terminator rune) (string, error) {
	if t.s.Peek() == scanner.EOF {
		input, err := t.prompt.InitialPrompt()
		if err != nil {
			return "", err
		}
		t.initScanner(input)
	}
	var query string
WholeQuery:
	for true {
		for tok := t.s.Scan(); tok != scanner.EOF; tok = t.s.Scan() {
			if tok == terminator {
				break WholeQuery
			}
			query += t.s.TokenText()
		}
		if terminator == '\n' {
			break
		}
		input, err := t.prompt.ContinuePrompt()
		if err != nil {
			return "", err
		}
		t.initScanner(input)
		query += "\n" // User started a new line.
	}
	if terminator == '\n' {
		t.prompt.AppendHistory(query)
	} else {
		t.prompt.AppendHistory(query + string(terminator))
	}
	return query, nil
}

type prompter interface {
	Close()
	InitialPrompt() (string, error)
	ContinuePrompt() (string, error)
	AppendHistory(query string)
}

// noninteractive prompter just blindly reads from stdin.
type noninteractive struct {
	input *bufio.Reader
}

// NewNonInteractive returns a T that simply reads input from stdin. Useful
// for when the user is piping input from a file or another program.
func NewNonInteractive() *T {
	return newT(&noninteractive{bufio.NewReader(os.Stdin)})
}

func (i *noninteractive) Close() {
}

func (i *noninteractive) InitialPrompt() (string, error) {
	return i.input.ReadString('\n')
}

func (i *noninteractive) ContinuePrompt() (string, error) {
	return i.input.ReadString('\n')
}

func (i *noninteractive) AppendHistory(query string) {
}

// interactive prompter provides a nice prompt for a user to input queries.
type interactive struct {
	line *liner.State
}

// NewInteractive returns a T that prompts the user for input.
func NewInteractive() *T {
	i := &interactive{
		line: liner.NewLiner(),
	}
	i.line.SetCtrlCAborts(true)
	return newT(i)
}

func (i *interactive) Close() {
	i.line.Close()
}

func (i *interactive) InitialPrompt() (string, error) {
	return i.line.Prompt("? ")
}

func (i *interactive) ContinuePrompt() (string, error) {
	return i.line.Prompt("  > ")
}

func (i *interactive) AppendHistory(query string) {
	i.line.AppendHistory(query)
}
