// 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/x/lib/vlog"
)

var (
	mounttable  = flag.String("mounttable", "/ns.dev.v.io:8101", "Mounttable where channel is mounted.")
	proxy       = flag.String("proxy", "proxy", "Proxy to listen on.")
	channelName = flag.String("channel", "users/vanadium.bot@gmail.com/apps/chat/public", "Channel to join.")
)

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, *channelName)
	if err != nil {
		log.Panicln(err)
	}

	historyView, err := g.View("history")
	if err != nil {
		log.Panicln(err)
	}
	hw := newHistoryWriter(historyView, 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.Quit
}

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, err := a.g.View("members")
	if err != nil {
		log.Panicln(err)
	}

	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.Quit {
		return err
	}

	return nil
}

func main() {
	flag.Parse()

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