// 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 main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/fatih/color"
	"github.com/nlacasse/gocui"

	"v.io/v23"
	"v.io/v23/naming"

	"v.io/x/lib/vlog"
)

var (
	mounttable = flag.String("mounttable", "/ns.dev.v.io:8101", "Mounttable where channel is mounted.")
	proxy      = flag.String("proxy", "proxy.dev.v.io:8100", "Proxy to listen on.")
	// TODO(nlacasse): Allow these to be set by a flag.
	appName     = "apps/chat"
	channelName = "public"
)

const welcomeText = `***Welcome to Vanadium Chat***
Press Ctrl-C to exit.
`

func init() {
	logDir, err := ioutil.TempDir("", "chat-logs")
	if err != nil {
		panic(err)
	}
	err = vlog.Log.Configure(vlog.LogDir(logDir))
	if err != nil {
		panic(err)
	}

	// Make sure that *nothing* ever gets printed to stderr.
	os.Stderr.Close()
}

// Defines the layout of the UI.
func layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()

	membersViewWidth := 30
	messageInputViewHeight := 3

	if _, err := g.SetView("history", -1, -1, maxX-membersViewWidth, maxY-messageInputViewHeight); err != nil {
		if err != gocui.ErrorUnkView {
			return err
		}
	}
	if membersView, err := g.SetView("members", maxX-membersViewWidth, -1, maxX, maxY-messageInputViewHeight); err != nil {
		if err != gocui.ErrorUnkView {
			return err
		}
		membersView.FgColor = gocui.ColorCyan
	}
	if messageInputView, err := g.SetView("messageInput", -1, maxY-messageInputViewHeight, maxX, maxY-1); err != nil {
		if err != gocui.ErrorUnkView {
			return err
		}
		messageInputView.Editable = true
	}
	if err := g.SetCurrentView("messageInput"); err != nil {
		return err
	}
	return nil
}

// app encapsulates the UI and the channel logic.
type app struct {
	cr            *channel
	g             *gocui.Gui
	hw            *historyWriter
	cachedMembers []string
	// Function to call when shutting down the app.
	shutdown func()
	// Mutex to protect read/writes to cachedMembers array.
	mu sync.Mutex
}

// Initialize the UI and channel.
func newApp() *app {
	// Set up the UI.
	g := gocui.NewGui()
	if err := g.Init(); err != nil {
		log.Panicln(err)
	}
	g.ShowCursor = true
	g.SetLayout(layout)

	// Draw the layout.
	g.Flush()

	ctx, ctxShutdown := v23.Init()

	shutdown := func() {
		ctxShutdown()
		g.Close()
	}

	cr, err := newChannel(ctx, *mounttable, *proxy, naming.Join(appName, channelName))
	if err != nil {
		log.Panicln(err)
	}

	hw := newHistoryWriter(g.View("history"), cr.UserName())
	hw.Write([]byte(color.RedString(welcomeText)))

	hw.Write([]byte(fmt.Sprintf("You have joined channel '%s' on mounttable '%s'.\n"+
		"Your username is '%s'.\n\n", channelName, *mounttable, cr.UserName())))

	a := &app{
		cr:       cr,
		g:        g,
		hw:       hw,
		shutdown: shutdown,
	}

	if err := a.setKeybindings(); err != nil {
		log.Panicln(err)
	}

	return a
}

// Helper method to log to the history console when debugging.
func (a *app) log(m string) {
	a.hw.Write([]byte("LOG: " + m + "\n"))
}

func (a *app) quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrorQuit
}

func (a *app) handleSendMessage(g *gocui.Gui, v *gocui.View) error {
	text := strings.TrimSpace(v.Buffer())
	if text == "" {
		return nil
	}
	if err := a.cr.broadcastMessage(text); err != nil {
		return err
	}
	v.Clear()
	return nil
}

func (a *app) handleTabComplete(g *gocui.Gui, v *gocui.View) error {
	lastWord, err := v.Word(v.Cursor())
	if err != nil {
		// The view buffer is empty.  Just return early.
		return nil
	}

	// Get a list of names that match the last word.
	matchedNames := []string{}
	a.mu.Lock()
	for _, name := range a.cachedMembers {
		if strings.HasPrefix(name, lastWord) {
			matchedNames = append(matchedNames, name)
		}
	}
	a.mu.Unlock()

	if len(matchedNames) == 0 {
		return nil
	}

	// Get the longest common prefix between the matchedNames.
	lcp := longestCommonPrefix(matchedNames)

	// Suffix is the part of the lcp that is not already part of the
	// lastWord.
	suffix := lcp[len(lastWord):]

	// If the name was matched uniquely, append a space.
	if len(matchedNames) == 1 {
		suffix = suffix + " "
	}

	// Simply writing the suffix to the buffer causes strange whitespace
	// additions. To work around this, we calculate the desired content of
	// the buffer, then clear the buffer and write the entire new content.
	newLine := strings.TrimSpace(v.Buffer()) + suffix
	v.Clear()
	v.Write([]byte(newLine))

	// Set the cursor to the end of the new line, and reset the origin.
	v.SetCursor(len(newLine), 0)
	v.SetOrigin(0, 0)

	return nil
}

func (a *app) setKeybindings() error {
	// Ctrl-C => Exit.
	if err := a.g.SetKeybinding("", gocui.KeyCtrlC, 0, a.quit); err != nil {
		return err
	}

	// Enter => Send message.
	if err := a.g.SetKeybinding("messageInput", gocui.KeyEnter, 0, a.handleSendMessage); err != nil {
		return err
	}

	// Tab => Tab-complete member names.
	if err := a.g.SetKeybinding("messageInput", gocui.KeyTab, 0, a.handleTabComplete); err != nil {
		return err
	}

	return nil
}

// updateMembers gets the members from the channel and writes them to the
// members view. It also caches the members in app.cachedMembers for use in tab
// autocomplete.
func (a *app) updateMembers() {
	membersView := a.g.View("members")

	members, err := a.cr.getMembers()
	if err != nil {
		log.Panicln(err)
	}

	memberNames := make([]string, len(members))

	for i, member := range members {
		memberNames[i] = member.Name
	}

	uniqMemberNames := uniqStrings(memberNames)

	membersView.Clear()
	for _, memberName := range uniqMemberNames {
		membersView.Write([]byte(memberName + "\n"))
	}

	a.mu.Lock()
	a.cachedMembers = uniqMemberNames
	a.mu.Unlock()
	a.g.Flush()
}

// displayIncomingMessages listens for incoming messages and writes them to the
// historyWriter.
func (a *app) displayIncomingMessages() {
	go func() {
		for {
			m := <-a.cr.messages
			a.hw.writeMessage(m)
		}
	}()
}

// run joins the channel and starts the main app loop.
func (a *app) run() error {
	// Join the channel.
	if err := a.cr.join(); err != nil {
		log.Panicln(err)
	}
	defer a.cr.leave()

	// Update the members view in a loop.
	go func() {
		for {
			a.updateMembers()
			time.Sleep(2 * time.Second)
		}
	}()

	a.displayIncomingMessages()

	// Start the main UI loop.
	if err := a.g.MainLoop(); err != nil && err != gocui.ErrorQuit {
		return err
	}

	return nil
}

func main() {
	flag.Parse()

	a := newApp()
	defer a.shutdown()
	if err := a.run(); err != nil {
		log.Panicln(err)
	}
}
