package main

import (
	"context"
	"fmt"
	"strings"
	"time"

	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
	"github.com/golang/glog"
)

// telegramConnection runs a long-lived connection to the Telegram API to receive
// updates and pipe resulting messages into telLog.
func (s *server) telegramConnection(ctx context.Context) error {
	u := tgbotapi.NewUpdate(0)
	// TODO(q3k): figure out what the _fuck_ does this even mean
	u.Timeout = 60

	updates, err := s.tel.GetUpdatesChan(u)
	if err != nil {
		return fmt.Errorf("GetUpdatesChan(%+v): %v", u, err)
	}

	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case u, ok := <-updates:
			if !ok {
				return fmt.Errorf("Updates channel closed")
			}

			// Dispatch update.
			switch {
			case u.Message != nil:
				if u.Message.Chat.ID != s.groupId {
					glog.Infof("[ignored group %d] <%s> %v", u.Message.Chat.ID, u.Message.From, u.Message.Text)
					continue
				}
				date := time.Unix(int64(u.Message.Date), 0)
				if time.Since(date) > 2*time.Minute {
					glog.Infof("[old message] <%s> %v", u.Message.From, u.Message.Text)
					continue
				}
				if msg := plainFromTelegram(s.tel.Self.ID, &u); msg != nil {
					s.telLog <- msg
				}
			}
		}
	}
}

// telegramLoop maintains a telegramConnection.
func (s *server) telegramLoop(ctx context.Context) {
	for {
		err := s.telegramConnection(ctx)
		if err == ctx.Err() {
			glog.Infof("Telegram connection closing: %v", err)
			return
		}

		glog.Errorf("Telegram connection error: %v", err)
		select {
		case <-ctx.Done():
			return
		case <-time.After(1 * time.Second):
			continue
		}
	}
}

// plainFromTelegram turns a Telegram message into a plain text message.
func plainFromTelegram(selfID int, u *tgbotapi.Update) *telegramPlain {
	parts := []string{}

	from := u.Message.From
	replyto := u.Message.ReplyToMessage
	text := u.Message.Text

	// This message is in reply to someone.
	if replyto != nil && text != "" && replyto.From != nil {
		// The rendered name of the author of the quote.
		ruid := "@" + replyto.From.String()

		// First line of the quoted text.
		quotedLine := ""

		// Check if the quoted message is from our bridge.
		if replyto.From.ID == selfID {
			// Someone replied to an IRC bridge message, extract nick and line from there
			// eg: "<q3k> foo bar baz" -> ruid = q3k; quotedLine = foo bar baz
			t := replyto.Text
			if strings.HasPrefix(t, "<") {
				p := strings.SplitN(t[1:], ">", 2)
				nick := p[0]
				quoted := strings.TrimSpace(p[1])

				// ensure nick looks sane
				if len(nick) < 16 && len(strings.Fields(nick)) == 1 {
					quotedLine = strings.TrimSpace(strings.Split(quoted, "\n")[0])
					ruid = nick
				}
			}
		} else {
			// Someone replied to a native telegram message.
			quoted := strings.TrimSpace(replyto.Text)
			quotedLine = strings.TrimSpace(strings.Split(quoted, "\n")[0])
		}

		// If we have a line, quote it. Otherwise just refer to the nick without a quote.
		if quotedLine != "" {
			parts = append(parts, fmt.Sprintf("%s: >%s\n", ruid, quotedLine))
		} else {
			parts = append(parts, fmt.Sprintf("%s: ", ruid))
		}
	}

	// This message contains a sticker.
	if u.Message.Sticker != nil {
		emoji := ""
		if u.Message.Sticker.SetName != "" {
			emoji += "/" + u.Message.Sticker.SetName
		}
		if u.Message.Sticker.Emoji != "" {
			emoji += "/" + u.Message.Sticker.Emoji
		}
		parts = append(parts, fmt.Sprintf("<sticker%s>", emoji))
	}

	// Mutually exclusive stuff.
	switch {
	case u.Message.Animation != nil:
		// This message contains an animation.
		a := u.Message.Animation
		parts = append(parts, fmt.Sprintf("<uploaded animation: %s >\n", fileURL(a.FileID, "mp4")))

	case u.Message.Document != nil:
		// This message contains a document.
		d := u.Message.Document
		fnp := strings.Split(d.FileName, ".")
		ext := "bin"
		if len(fnp) > 1 {
			ext = fnp[len(fnp)-1]
		}
		parts = append(parts, fmt.Sprintf("<uploaded file: %s >\n", fileURL(d.FileID, ext)))

	case u.Message.Photo != nil:
		// This message contains a photo.
		// Multiple entries are for different file sizes, choose the highest quality one.
		hq := (*u.Message.Photo)[0]
		for _, p := range *u.Message.Photo {
			if p.FileSize > hq.FileSize {
				hq = p
			}
		}
		parts = append(parts, fmt.Sprintf("<uploaded photo: %s >\n", fileURL(hq.FileID, "jpg")))
	}

	// This message has some plain text.
	if text != "" {
		parts = append(parts, text)
	}

	// Was there anything that we extracted?
	if len(parts) > 0 {
		return &telegramPlain{from.String(), strings.Join(parts, " ")}
	}
	return nil
}

func fileURL(fid, ext string) string {
	return flagTeleimgRoot + fid + "." + ext
}
